```\n/\*\*\n \* @notice Checks that a leaf hash is contained in a root hash\n \* @param leaf Leaf hash to verify\n \* @param index Position of the leaf hash in the Merkle tree\n \* @param rootHash Root of the Merkle tree\n \* @param proof A Merkle proof demonstrating membership of the leaf hash\n \* @return True, if the leaf hash is in the Merkle tree; otherwise, False\n\*/\nfunction checkMembership(bytes32 leaf, uint256 index, bytes32 rootHash, bytes memory proof)\n    internal\n    pure\n    returns (bool)\n{\n    require(proof.length % 32 == 0, "Length of Merkle proof must be a multiple of 32");\n\n    bytes32 proofElement;\n    bytes32 computedHash = leaf;\n    uint256 j = index;\n    // Note: We're skipping the first 32 bytes of `proof`, which holds the size of the dynamically sized `bytes`\n    for (uint256 i = 32; i <= proof.length; i += 32) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            proofElement := mload(add(proof, i))\n        }\n        if (j % 2 == 0) {\n            computedHash = keccak256(abi.encodePacked(computedHash, proofElement));\n        } else {\n            computedHash = keccak256(abi.encodePacked(proofElement, computedHash));\n        }\n        j = j / 2;\n    }\n\n    return computedHash == rootHash;\n}\n```\n