MEDIUM severity: The LibMuon library is vulnerable to a signature hash collision attack due to its use of `abi.encode. The LibMuon library is vulnerable to a signature hash collision attack due to its use of `abi.encodePacked` when calculating the hash. This allows for the substitution of malicious signatures for legitimate ones, as the same hash value can be generated for different structures. \n\nThe `verifyPrices...

Vulnerable code:
```\nfunction verifyPrices(PriceSig memory priceSig, address partyA) internal view {\n    MuonStorage.Layout storage muonLayout = MuonStorage.layout();\n    require(priceSig.prices.length == priceSig.symbolIds.length, "LibMuon: Invalid length");\n    bytes32 hash = keccak256(\n        abi.encodePacked(\n            muonLayout.muonAppId,\n            priceSig.reqId,\n            address(this),\n            partyA,\n            priceSig.upnl,\n            priceSig.totalUnrealizedLoss,\n            priceSig.symbolIds,\n            priceSig.prices,\n            priceSig.timestamp,\n            getChainId()\n        )\n    );\n    verifyTSSAndGateway(hash, priceSig.sigs, priceSig.gatewaySignature);\n}\n```\n```\nfunction verifyPartyAUpnlAndPrice(\n    SingleUpnlAndPriceSig memory upnlSig,\n    address partyA,\n    uint256 symbolId\n) internal view {\n    MuonStorage.Layout storage muonLayout = MuonStorage.layout();\n\n    bytes32 hash = keccak256(\n        abi.encodePacked(\n            muonLayout.muonAppId,\n            upnlSig.reqId,\n            address(this),\n            partyA,\n            AccountStorage.layout().partyANonces[partyA],\n            upnlSig.upnl,\n            symbolId,\n            upnlSig.price,\n            upnlSig.timestamp,\n            getChainId()\n        )\n    );\n    verifyTSSAndGateway(hash, upnlSig.sigs, upnlSig.gatewaySignature);\n}\n```\n```\nfunction test() external {\n    address verifyPrices_partyA = address(0x1);\n    int256 verifyPrices_upnl = 100;\n    int256 verifyPrices_totalUnrealizedLoss = 100;\n    uint256[] memory verifyPrices_symbolIds = new uint256[](1);\n    verifyPrices_symbolIds[0] = 1;\n    uint256[] memory verifyPrices_prices = new uint256[](1);\n    verifyPrices_prices[0] = 1000;\n\n    bytes32 verifyPrices = keccak256(abi.encodePacked(\n        verifyPrices_partyA,\n        verifyPrices_upnl,\n        verifyPrices_totalUnrealizedLoss,\n        verifyPrices_symbolIds,\n        verifyPrices_prices\n    ));\n\n    address verifyPartyAUpnlAndPrice_partyA = verifyPrices_partyA;\n    int256 verifyPartyAUpnlAndPrice_partyANonces = verifyPrices_upnl;\n    int256 verifyPartyAUpnlAndPrice_upnl = verifyPrices_totalUnrealizedLoss;\n    uint256 verifyPartyAUpnlAndPrice_symbolId = verifyPrices_symbolIds[0];\n    uint256 verifyPartyAUpnlAndPrice_price = verifyPrices_prices[0];\n\n    bytes32 verifyPartyAUpnlAndPrice = keccak256(abi.encodePacked(\n        verifyPartyAUpnlAndPrice_partyA,\n        verifyPartyAUpnlAndPrice_partyANonces,\n        verifyPartyAUpnlAndPrice_upnl,\n        verifyPartyAUpnlAndPrice_symbolId,\n        verifyPartyAUpnlAndPrice_price\n    ));\n\n    console.log("verifyPrices == verifyPartyAUpnlAndPrice:", verifyPrices == verifyPartyAUpnlAndPrice);\n}\n```\n```\n$ forge test -vvv\n\nRunning 1 test for test/Counter.t.sol:CounterTest\n[PASS] test() (gas: 4991)\nLogs:\n  verifyPrices == verifyPartyAUpnlAndPrice: true\n\nTest result: ok. 1 passed; 0 failed; finished in 11.27ms\n```