Introduction

Example 1: Transfer mETH to ITB PositionManager

{
  "AddressArguments": ["0x919531146f9a25dFC161D5AB23B117FeAE2c1d36"],
  "CanSendValue": False,
  "DecoderAndSanitizerAddress": "0xa728337af7dD226B74B0b1546AA7dD54d340d5Eb",
  "Description": "Transfer mETH to ITB Contract: 0x919531146f9a25dFC161D5AB23B117FeAE2c1d36",
  "FunctionSelector": "0xa9059cbb",
  "FunctionSignature": "transfer(address,uint256)",
  "LeafDigest": "0x89cd1ab1bdfb632a52b4d7e7de0e45eed164d7e7fa9b02916e87b945e37ba94c",
  "PackedArgumentAddresses": "0x919531146f9a25dfc161d5ab23b117feae2c1d36",
  "TargetAddress": "0xd5F7838F5C461fefF7FE49ea5ebaF7728bB0ADfa",
}

We can see from the description that this leaf authorizes transferring mETH to address 0x919531146f9a25dFC161D5AB23B117FeAE2c1d36 which corresponds to the ITB PositionManager for Symbiotic.

Construct the Merkle Proof

The LeafDigest for this leaf is 0x89cd1ab1bdfb632a52b4d7e7de0e45eed164d7e7fa9b02916e87b945e37ba94c.

This script produces the Merkle proof from the LeafDigest:

import json
from typing import List, Dict

def construct_merkle_proof(leaf_digest: str, tree_data: Dict) -> List[str]:
    # Convert leaf_digest to lowercase for case-insensitive comparison
    leaf_digest = leaf_digest.lower()
    
    # Find the leaf index
    leaf_index = None
    for i, digest in enumerate(tree_data['MerkleTree']['6']):
        if digest.lower() == leaf_digest:
            leaf_index = i
            break
    
    if leaf_index is None:
        raise ValueError("Leaf digest not found in the tree")

    proof = []
    current_index = leaf_index

    # Traverse up the tree
    for level in range(6, 0, -1):
        is_right = current_index % 2 == 1
        sibling_index = current_index - 1 if is_right else current_index + 1
        
        if sibling_index < len(tree_data['MerkleTree'][str(level)]):
            sibling_digest = tree_data['MerkleTree'][str(level)][sibling_index]
            proof.append(sibling_digest)
        
        current_index //= 2  # Move to the parent node

    return proof

# Example usage:
def main():
    # Load the tree data from a JSON file or string
    with open('tree_data.json', 'r') as f:
        tree_data = json.load(f)

    # Example leaf digest
    leaf_digest = "0x89cd1ab1bdfb632a52b4d7e7de0e45eed164d7e7fa9b02916e87b945e37ba94c"

    try:
        merkle_proof = construct_merkle_proof(leaf_digest, tree_data)
        print(f"Merkle Proof for leaf {leaf_digest}:")
        print(merkle_proof)
    except ValueError as e:
        print(f"Error: {e}")

if __name__ == "__main__":
    main()

The output of the script is

[["0xd7e0a9c6d4a965ce0062e728269fe11ee10f6b82debbd2241e7363a951ac9f9c", "0x91a1565472bec1d7d1b83fa70e3940f990f60e7b1b7784adbe36a7ecf01854ae", "0xa529bcb69360978ab9ab57d087daabac89a3a07cc163755994434af4cc56e5f1", "0xef477b38d1acbe665785e8636992323a9a3ce750dcf40fd6e49d6c89d29b8119", "0x500fb7061ee25014f3761d130c907e2458e5ac555c54703e7237ef38500a2996", "0x805d86b669a6c46b9f8e66f302ed1088ce92d665a7105d7ecb0385fa352aa007"]]