From 7cfc4725cb3e72c3e055124823ab1dc5ad9e85cf Mon Sep 17 00:00:00 2001 From: mfw78 Date: Mon, 3 Aug 2026 00:57:23 +0000 Subject: [PATCH] build!: replace OpenZeppelin with solady `src` used OpenZeppelin for two things: `MerkleProof.verify` at a single call site, and `SafeCast.toUint32` in three files. Both have direct solady equivalents, and `MerkleProofLib.verify` has a memory variant matching the existing call exactly, so the swap is mechanical. murky goes too. Its `Merkle` was only used by the test helper, and solady's `MerkleTreeLib` covers the same surface. That also removes the transitive `openzeppelin-contracts` murky vendored, so this is a real removal rather than a partial one, and it means trees are now built and verified by the same family: `ComposableCow` verifies with `MerkleProofLib`, and `MerkleTreeLib` is designed to pair with it. The two libraries are not interchangeable, which was worth checking rather than assuming. For leaf counts that are not powers of two they build different trees: 3, 5, 6, 7 and 9 all diverge, while 2, 4 and 8 agree. What holds either way is that a proof verifies against a root from the same library, which is the only property anything here relies on, since each tree is built and verified by one library. Nothing mixes them. Measured against the same Safe, forge-std and optimizer settings, so this isolates the dependency change: 95 of 128 snapshot entries move setRootWithContext_e2e -41,025 setRoot_e2e -41,003 settle_e2e -39,552 setSwapGuard_e2e -11,330 payloadTree -7,210 createAndRemove -5,786 35 entries rise, none by more than 45 total -152,161 gas The merkle-heavy paths dominate, which is what you would expect when the tree library changes. The median entry is unchanged. `ComposableCow` also drops from 10,659 to 10,595 bytes. The rest are unchanged in size, which is expected: only the merkle and cast paths moved. Test mocks move too, so this is a removal rather than a partial one. `MockERC20` is rebuilt on solady's `ERC20`, which declares `name` and `symbol` abstract instead of storing them in the base, so the mock now holds them. `GPv2TradeEncoder` took `IERC20` from OpenZeppelin where cowprotocol's is the one every other type uses, so it now takes cowprotocol's. The `IERC20` in `GPv2Order.Data` was never OpenZeppelin's. It comes from cowprotocol through `IConditionalOrder` and `BaseConditionalOrder`, so handler `Data` structs were already consistent with the settlement types and nothing about that changes here. `getRootAndProof` loses its two function pointers. They existed to inject murky's `getRoot` and `getProof`, and with `MerkleTreeLib` called directly there is nothing to inject. Four submodules remain: forge-std, cowprotocol, safe and solady. --- .gas-snapshot | 268 +++++++++++++------------ .gitmodules | 9 +- docs/discovery.md | 2 +- foundry.lock | 14 +- lib/@openzeppelin | 1 - lib/murky | 1 - lib/solady | 1 + remappings.txt | 6 +- src/ComposableCow.sol | 4 +- src/types/GoodAfterTime.sol | 4 +- src/types/twap/TWAP.sol | 4 +- src/types/twap/libraries/TWAPOrder.sol | 4 +- test/ComposableCow.base.t.sol | 4 +- test/ComposableCow.proof.t.sol | 10 +- test/ComposableCow.t.sol | 4 +- test/ComposableCow.twap.t.sol | 4 +- test/helpers/Tokens.t.sol | 22 +- test/libraries/ComposableCowLib.t.sol | 20 +- test/vendored/GPv2TradeEncoder.sol | 2 +- 19 files changed, 198 insertions(+), 186 deletions(-) delete mode 160000 lib/@openzeppelin delete mode 160000 lib/murky create mode 160000 lib/solady diff --git a/.gas-snapshot b/.gas-snapshot index a9e811b6..8e87ad82 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,166 +1,172 @@ BaseComposableCowTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10756) BaseComposableCowTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17449) -ComposableCowDiscoveryTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10757) +ComposableCowDescriptorDocTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10778) +ComposableCowDescriptorDocTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17449) +ComposableCowDescriptorDocTest:test_descriptor_ComponentCountMatchesEncodedWidth() (gas: 50546) +ComposableCowDescriptorDocTest:test_descriptor_ObservedReasonCodeIsDocumented() (gas: 112552) +ComposableCowDescriptorDocTest:test_descriptor_SelectorMatchesDeclaredName() (gas: 173216) +ComposableCowDescriptorDocTest:test_descriptor_SelectorsAreDistinct() (gas: 153864) +ComposableCowDiscoveryTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10734) ComposableCowDiscoveryTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17449) -ComposableCowDiscoveryTest:test_descriptor_CommittedAdvertisesAndRoundTrips() (gas: 2196729) -ComposableCowDiscoveryTest:test_descriptor_ConstructorEmitsUpdate() (gas: 2193542) -ComposableCowDiscoveryTest:test_descriptor_UncommittedDoesNotAdvertise() (gas: 2097654) -ComposableCowDiscoveryTest:test_module_CommittedAdvertisesAndRoundTrips() (gas: 1671095) +ComposableCowDiscoveryTest:test_descriptor_CommittedAdvertisesAndRoundTrips() (gas: 2196685) +ComposableCowDiscoveryTest:test_descriptor_ConstructorEmitsUpdate() (gas: 2193564) +ComposableCowDiscoveryTest:test_descriptor_UncommittedDoesNotAdvertise() (gas: 2097676) +ComposableCowDiscoveryTest:test_module_CommittedAdvertisesAndRoundTrips() (gas: 1671117) ComposableCowDiscoveryTest:test_module_ContentAddressedNeedsNoURI() (gas: 1571005) -ComposableCowDiscoveryTest:test_module_NeedsInputSignal() (gas: 1578945) -ComposableCowDiscoveryTest:test_module_RevertsContentAddressedWithURI() (gas: 39798) -ComposableCowDiscoveryTest:test_module_RevertsSha256WithoutURI() (gas: 38874) +ComposableCowDiscoveryTest:test_module_NeedsInputSignal() (gas: 1578967) +ComposableCowDiscoveryTest:test_module_RevertsContentAddressedWithURI() (gas: 39842) +ComposableCowDiscoveryTest:test_module_RevertsSha256WithoutURI() (gas: 38851) ComposableCowDiscoveryTest:test_module_RevertsUncommittedURI() (gas: 39797) -ComposableCowDiscoveryTest:test_module_UncommittedDoesNotAdvertise() (gas: 1568521) -ComposableCowForwarderTest:test_ERC1271Forwarder_isValidSignature_RevertsOnBadHash() (gas: 676780) -ComposableCowForwarderTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10734) +ComposableCowDiscoveryTest:test_module_UncommittedDoesNotAdvertise() (gas: 1568479) +ComposableCowForwarderTest:test_ERC1271Forwarder_isValidSignature_RevertsOnBadHash() (gas: 670453) +ComposableCowForwarderTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10756) ComposableCowForwarderTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17449) -ComposableCowGatTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10757) -ComposableCowGatTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17494) -ComposableCowGatTest:test_generateOrder_FuzzContext(address,address,address,uint256,uint256,uint256,uint256,bool) (runs: 256, μ: 111690, ~: 111690) -ComposableCowGatTest:test_generateOrder_FuzzRevertBeforeStartTime(uint256,uint256) (runs: 256, μ: 21910, ~: 21910) -ComposableCowGatTest:test_generateOrder_FuzzRevertBelowMinBalance(uint256,uint256) (runs: 256, μ: 106447, ~: 106448) -ComposableCowGatTest:test_generateOrder_FuzzRevertTooLowOutput(uint256,uint256,uint256) (runs: 256, μ: 116452, ~: 116573) -ComposableCowGatTest:test_generateOrder_RevertZeroAmount() (gas: 105397) -ComposableCowGatTest:test_generateOrder_e2e_Fuzz(uint256,uint256,uint256,uint256,uint256,uint256) (runs: 256, μ: 288171, ~: 288117) -ComposableCowGatTest:test_generateOrder_e2e_FuzzWithPriceChecker(uint256,uint256,uint256,uint256,uint256) (runs: 256, μ: 296982, ~: 296751) -ComposableCowGatTest:test_pollHints_SingleShot() (gas: 13476) -ComposableCowGatTest:test_settle_e2e() (gas: 484216) -ComposableCowGatTest:test_verify_e2e_fuzz(uint256,uint256,uint256,uint256,uint256) (runs: 256, μ: 128446, ~: 128215) -ComposableCowGuardsTest:test_BaseSwapGuard_supportsInterface() (gas: 172757) -ComposableCowGuardsTest:test_ReceiverLock_verify_FuzzRevertsWhenReceiverNotSelf(address) (runs: 256, μ: 331323, ~: 331323) -ComposableCowGuardsTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10756) +ComposableCowGatTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10734) +ComposableCowGatTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17472) +ComposableCowGatTest:test_generateOrder_FuzzContext(address,address,address,uint256,uint256,uint256,uint256,bool) (runs: 256, μ: 111622, ~: 111623) +ComposableCowGatTest:test_generateOrder_FuzzRevertBeforeStartTime(uint256,uint256) (runs: 256, μ: 21865, ~: 21865) +ComposableCowGatTest:test_generateOrder_FuzzRevertBelowMinBalance(uint256,uint256) (runs: 256, μ: 106396, ~: 106398) +ComposableCowGatTest:test_generateOrder_FuzzRevertTooLowOutput(uint256,uint256,uint256) (runs: 256, μ: 116357, ~: 116471) +ComposableCowGatTest:test_generateOrder_RevertZeroAmount() (gas: 105370) +ComposableCowGatTest:test_generateOrder_e2e_Fuzz(uint256,uint256,uint256,uint256,uint256,uint256) (runs: 256, μ: 287894, ~: 287833) +ComposableCowGatTest:test_generateOrder_e2e_FuzzWithPriceChecker(uint256,uint256,uint256,uint256,uint256) (runs: 256, μ: 296668, ~: 296449) +ComposableCowGatTest:test_pollHints_SingleShot() (gas: 13498) +ComposableCowGatTest:test_settle_e2e() (gas: 479566) +ComposableCowGatTest:test_verify_e2e_fuzz(uint256,uint256,uint256,uint256,uint256) (runs: 256, μ: 128357, ~: 128138) +ComposableCowGuardsTest:test_BaseSwapGuard_supportsInterface() (gas: 172734) +ComposableCowGuardsTest:test_ReceiverLock_verify_FuzzRevertsWhenReceiverNotSelf(address) (runs: 256, μ: 331172, ~: 331172) +ComposableCowGuardsTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10778) ComposableCowGuardsTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17449) -ComposableCowGuardsTest:test_setSwapGuard_FuzzSetAndEmit(address,address) (runs: 256, μ: 30024, ~: 30007) -ComposableCowGuardsTest:test_setSwapGuard_e2e() (gas: 1082707) -ComposableCowManifestTest:test_PSS_ManifestPage_NotFundedCarriesStatus() (gas: 36217) -ComposableCowManifestTest:test_PSS_ManifestPage_WithBalance() (gas: 116851) +ComposableCowGuardsTest:test_setSwapGuard_FuzzSetAndEmit(address,address) (runs: 256, μ: 30025, ~: 30007) +ComposableCowGuardsTest:test_setSwapGuard_e2e() (gas: 1071377) +ComposableCowManifestTest:test_PSS_ManifestPage_NotFundedCarriesStatus() (gas: 36073) +ComposableCowManifestTest:test_PSS_ManifestPage_WithBalance() (gas: 116673) ComposableCowManifestTest:test_PSS_ManifestReturnsUnbounded() (gas: 13490) -ComposableCowManifestTest:test_PSS_PaginationAlwaysTerminates() (gas: 116435) +ComposableCowManifestTest:test_PSS_PaginationAlwaysTerminates() (gas: 116257) ComposableCowManifestTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10757) -ComposableCowManifestTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17472) -ComposableCowManifestTest:test_TWAP_IsActive_DuringSpan() (gas: 36949) -ComposableCowManifestTest:test_TWAP_ManifestEntriesMatchGenerateOrder() (gas: 342893) +ComposableCowManifestTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17450) +ComposableCowManifestTest:test_TWAP_IsActive_DuringSpan() (gas: 36940) +ComposableCowManifestTest:test_TWAP_ManifestEntriesMatchGenerateOrder() (gas: 342794) ComposableCowManifestTest:test_TWAP_getManifestInfo_DegenerateYieldsEmptyManifest() (gas: 17211) ComposableCowManifestTest:test_TWAP_getManifestInfo_ReturnsExactCardinality() (gas: 17281) -ComposableCowManifestTest:test_TWAP_getManifestPage_Pagination() (gas: 154101) -ComposableCowManifestTest:test_TWAP_getManifestPage_ReturnsAllParts() (gas: 173396) -ComposableCowManifestTest:test_TWAP_getManifestPage_UninitializedCarriesStatus() (gas: 22359) -ComposableCowManifestTest:test_TWAP_getManifestPage_WithContext() (gas: 112565) -ComposableCowManifestTest:test_manifestInfo_DefaultSingleShot() (gas: 1546661) +ComposableCowManifestTest:test_TWAP_getManifestPage_Pagination() (gas: 154007) +ComposableCowManifestTest:test_TWAP_getManifestPage_ReturnsAllParts() (gas: 173324) +ComposableCowManifestTest:test_TWAP_getManifestPage_UninitializedCarriesStatus() (gas: 22381) +ComposableCowManifestTest:test_TWAP_getManifestPage_WithContext() (gas: 112550) +ComposableCowManifestTest:test_manifestInfo_DefaultSingleShot() (gas: 1546639) ComposableCowManifestTest:test_manifestPage_DefaultSingleEntry() (gas: 1705274) -ComposableCowManifestTest:test_manifestPage_EmptyPageCarriesInvalidReason() (gas: 1469787) -ComposableCowManifestTest:test_manifestPage_EmptyPageCarriesWaitReason() (gas: 1497815) +ComposableCowManifestTest:test_manifestPage_EmptyPageCarriesInvalidReason() (gas: 1469832) +ComposableCowManifestTest:test_manifestPage_EmptyPageCarriesWaitReason() (gas: 1497793) ComposableCowManifestTest:test_manifestPage_OutOfRangeTerminates() (gas: 1552113) ComposableCowManifestTest:test_manifest_DoesNotPerturbGeneratorInterfaceId() (gas: 325) -ComposableCowManifestTest:test_manifest_SupportsInterface() (gas: 1545445) +ComposableCowManifestTest:test_manifest_SupportsInterface() (gas: 1545467) ComposableCowPollTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10778) -ComposableCowPollTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17472) -ComposableCowPollTest:test_checkOrder_ComposesFillOverlay() (gas: 1838676) -ComposableCowPollTest:test_checkOrder_RevertInterfaceNotSupported() (gas: 49865) -ComposableCowPollTest:test_fillOverlay_FilledWithholdsSignature() (gas: 1839521) -ComposableCowPollTest:test_fillOverlay_ForeignOwnerOrderUidNotObserved() (gas: 1863061) -ComposableCowPollTest:test_fillOverlay_InvalidatedIsDistinctFromFilled() (gas: 1839408) -ComposableCowPollTest:test_fillOverlay_KindBuyTotalIsBuyAmount() (gas: 1839351) -ComposableCowPollTest:test_fillOverlay_KindSellSameAmountIsPartial() (gas: 1854123) -ComposableCowPollTest:test_fillOverlay_NoneReturnsSignature() (gas: 1853993) -ComposableCowPollTest:test_fillOverlay_OrderUidMatchesGPv2Construction() (gas: 1845902) -ComposableCowPollTest:test_fillOverlay_PartialFillKeepsPosting() (gas: 1854166) -ComposableCowPollTest:test_fillOverlay_PartialFillOnFillOrKillWithholdsSignature() (gas: 1819836) -ComposableCowPollTest:test_getTradeableOrderWithSignature_UsesPollInternally() (gas: 1542387) -ComposableCowPollTest:test_poll_BareRequireMapsToTryNextBlock() (gas: 1431295) -ComposableCowPollTest:test_poll_DecodesOrderNotValid() (gas: 1470363) -ComposableCowPollTest:test_poll_DecodesPollNeedsOffchainInput() (gas: 1516559) -ComposableCowPollTest:test_poll_DecodesPollTryAtBlock() (gas: 1498216) -ComposableCowPollTest:test_poll_DecodesPollTryAtTimestamp() (gas: 1498210) -ComposableCowPollTest:test_poll_DecodesPollTryNextBlock() (gas: 1470350) -ComposableCowPollTest:test_poll_FuzzOrderNotValid(bytes4) (runs: 256, μ: 1462820, ~: 1470361) -ComposableCowPollTest:test_poll_FuzzPollTryAtBlock(uint256,bytes4) (runs: 256, μ: 1490269, ~: 1498276) -ComposableCowPollTest:test_poll_FuzzPollTryAtTimestamp(uint256,bytes4) (runs: 256, μ: 1490218, ~: 1498225) -ComposableCowPollTest:test_poll_NeedsInputHandlerPostsWithInput() (gas: 1518926) -ComposableCowPollTest:test_poll_PanicMapsToTryNextBlock() (gas: 1428251) +ComposableCowPollTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17516) +ComposableCowPollTest:test_checkOrder_ComposesFillOverlay() (gas: 1838566) +ComposableCowPollTest:test_checkOrder_RevertInterfaceNotSupported() (gas: 49822) +ComposableCowPollTest:test_fillOverlay_FilledWithholdsSignature() (gas: 1839500) +ComposableCowPollTest:test_fillOverlay_ForeignOwnerOrderUidNotObserved() (gas: 1863041) +ComposableCowPollTest:test_fillOverlay_InvalidatedIsDistinctFromFilled() (gas: 1839365) +ComposableCowPollTest:test_fillOverlay_KindBuyTotalIsBuyAmount() (gas: 1839308) +ComposableCowPollTest:test_fillOverlay_KindSellSameAmountIsPartial() (gas: 1854080) +ComposableCowPollTest:test_fillOverlay_NoneReturnsSignature() (gas: 1853950) +ComposableCowPollTest:test_fillOverlay_OrderUidMatchesGPv2Construction() (gas: 1845860) +ComposableCowPollTest:test_fillOverlay_PartialFillKeepsPosting() (gas: 1854145) +ComposableCowPollTest:test_fillOverlay_PartialFillOnFillOrKillWithholdsSignature() (gas: 1819793) +ComposableCowPollTest:test_getTradeableOrderWithSignature_UsesPollInternally() (gas: 1542299) +ComposableCowPollTest:test_poll_BareRequireMapsToTryNextBlock() (gas: 1431317) +ComposableCowPollTest:test_poll_DecodesOrderNotValid() (gas: 1470341) +ComposableCowPollTest:test_poll_DecodesPollNeedsOffchainInput() (gas: 1516603) +ComposableCowPollTest:test_poll_DecodesPollTryAtBlock() (gas: 1498172) +ComposableCowPollTest:test_poll_DecodesPollTryAtTimestamp() (gas: 1498165) +ComposableCowPollTest:test_poll_DecodesPollTryNextBlock() (gas: 1470372) +ComposableCowPollTest:test_poll_FuzzOrderNotValid(bytes4) (runs: 256, μ: 1462698, ~: 1470316) +ComposableCowPollTest:test_poll_FuzzPollTryAtBlock(uint256,bytes4) (runs: 256, μ: 1490990, ~: 1498298) +ComposableCowPollTest:test_poll_FuzzPollTryAtTimestamp(uint256,bytes4) (runs: 256, μ: 1490983, ~: 1498291) +ComposableCowPollTest:test_poll_NeedsInputHandlerPostsWithInput() (gas: 1518881) +ComposableCowPollTest:test_poll_PanicMapsToTryNextBlock() (gas: 1428295) ComposableCowPollTest:test_poll_ReturnsPostOnValidOrder() (gas: 1769520) ComposableCowPollTest:test_poll_UnknownErrorMapsToTryNextBlock() (gas: 1421458) -ComposableCowPollTest:test_tryGenerateOrder_NeedsInputRevertData() (gas: 1521644) -ComposableCowPollTest:test_tryGenerateOrder_ReturnsFullCustomErrorData() (gas: 1427051) +ComposableCowPollTest:test_tryGenerateOrder_NeedsInputRevertData() (gas: 1521666) +ComposableCowPollTest:test_tryGenerateOrder_ReturnsFullCustomErrorData() (gas: 1427007) ComposableCowPollTest:test_tryGenerateOrder_ReturnsFullErrorString() (gas: 1448273) -ComposableCowPollTest:test_tryGenerateOrder_ReturnsFullPanicData() (gas: 1433822) -ComposableCowPollTest:test_tryGenerateOrder_SuccessReturnsOrder() (gas: 1683145) -ComposableCowPollTest:test_verify_RevertsOnHashMismatch() (gas: 1770259) +ComposableCowPollTest:test_tryGenerateOrder_ReturnsFullPanicData() (gas: 1433800) +ComposableCowPollTest:test_tryGenerateOrder_SuccessReturnsOrder() (gas: 1683167) +ComposableCowPollTest:test_verify_RevertsOnHashMismatch() (gas: 1770193) ComposableCowPollTest:test_verify_UsesGenerateOrder() (gas: 1767357) -ComposableCowProofTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10756) +ComposableCowProofTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10778) ComposableCowProofTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17449) -ComposableCowProofTest:test_payloadTree_NormativeConstructionVerifiesLikeAuth() (gas: 559704) -ComposableCowProofTest:test_setRoot_BlobSubsetAttached() (gas: 40651) -ComposableCowProofTest:test_setRoot_BlobsAttached() (gas: 42221) -ComposableCowProofTest:test_setRoot_EmitsUriMirrors() (gas: 47443) -ComposableCowProofTest:test_setRoot_RevertsBlobNotAttached() (gas: 14432) -ComposableCowProofTest:test_setRoot_RevertsBlobNotAttachedNoBlobs() (gas: 12510) -ComposableCowProofTest:test_setRoot_RevertsZeroRootWithBlobs() (gas: 13109) -ComposableCowProofTest:test_setRoot_RevertsZeroRootWithUris() (gas: 12318) -ComposableCowProofTest:test_setRoot_ZeroRootClears() (gas: 32510) -ComposableCowStopLossTest:test_OracleNormalisesPrice_concrete() (gas: 26448) -ComposableCowStopLossTest:test_OracleNormalisesPrice_fuzz(uint8,uint8,uint8,uint8) (runs: 256, μ: 29633, ~: 29736) -ComposableCowStopLossTest:test_OracleRevertOnExpiredOrder_fuzz(uint32,uint32) (runs: 256, μ: 23018, ~: 23018) -ComposableCowStopLossTest:test_OracleRevertOnInvalidPrice_fuzz(int256,int256) (runs: 256, μ: 36846, ~: 36846) +ComposableCowProofTest:test_payloadTree_NormativeConstructionVerifiesLikeAuth() (gas: 552494) +ComposableCowProofTest:test_setRoot_BlobSubsetAttached() (gas: 40629) +ComposableCowProofTest:test_setRoot_BlobsAttached() (gas: 42198) +ComposableCowProofTest:test_setRoot_EmitsUriMirrors() (gas: 47422) +ComposableCowProofTest:test_setRoot_RevertsBlobNotAttached() (gas: 14454) +ComposableCowProofTest:test_setRoot_RevertsBlobNotAttachedNoBlobs() (gas: 12445) +ComposableCowProofTest:test_setRoot_RevertsZeroRootWithBlobs() (gas: 13153) +ComposableCowProofTest:test_setRoot_RevertsZeroRootWithUris() (gas: 12340) +ComposableCowProofTest:test_setRoot_ZeroRootClears() (gas: 32492) +ComposableCowStopLossTest:test_OracleNormalisesPrice_concrete() (gas: 26470) +ComposableCowStopLossTest:test_OracleNormalisesPrice_fuzz(uint8,uint8,uint8,uint8) (runs: 256, μ: 29632, ~: 29736) +ComposableCowStopLossTest:test_OracleRevertOnExpiredOrder_fuzz(uint32,uint32) (runs: 256, μ: 23040, ~: 23040) +ComposableCowStopLossTest:test_OracleRevertOnInvalidPrice_fuzz(int256,int256) (runs: 256, μ: 36868, ~: 36868) ComposableCowStopLossTest:test_OracleRevertOnStalePrice_fuzz(uint256,uint256,uint256) (runs: 256, μ: 25079, ~: 25079) -ComposableCowStopLossTest:test_RevertStrikePriceNotMet_fuzz(int256,int256,int256,uint256,uint256) (runs: 256, μ: 27795, ~: 27795) -ComposableCowStopLossTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10735) +ComposableCowStopLossTest:test_RevertStrikePriceNotMet_fuzz(int256,int256,int256,uint256,uint256) (runs: 256, μ: 27817, ~: 27817) +ComposableCowStopLossTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10757) ComposableCowStopLossTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17449) -ComposableCowStopLossTest:test_generateOrder_RevertZeroAmount() (gas: 22393) -ComposableCowStopLossTest:test_pollHints_SingleShot() (gas: 13253) -ComposableCowStopLossTest:test_strikePriceMet_fuzz(int256,int256,int256,uint32) (runs: 256, μ: 27763, ~: 27763) -ComposableCowStopLossTest:test_strikePriceNotMet_concrete() (gas: 26274) -ComposableCowTatTest:test_BalanceMet_fuzz(address,uint256,bytes32,uint256) (runs: 256, μ: 105709, ~: 105695) -ComposableCowTatTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10734) +ComposableCowStopLossTest:test_generateOrder_RevertZeroAmount() (gas: 22348) +ComposableCowStopLossTest:test_pollHints_SingleShot() (gas: 13275) +ComposableCowStopLossTest:test_strikePriceMet_fuzz(int256,int256,int256,uint32) (runs: 256, μ: 27740, ~: 27740) +ComposableCowStopLossTest:test_strikePriceNotMet_concrete() (gas: 26296) +ComposableCowTatTest:test_BalanceMet_fuzz(address,uint256,bytes32,uint256) (runs: 256, μ: 105645, ~: 105631) +ComposableCowTatTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10756) ComposableCowTatTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17449) -ComposableCowTatTest:test_generateOrder_FuzzRevertBelowThreshold(uint256,uint256) (runs: 256, μ: 104780, ~: 104781) +ComposableCowTatTest:test_generateOrder_FuzzRevertBelowThreshold(uint256,uint256) (runs: 256, μ: 104693, ~: 104693) ComposableCowTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10734) ComposableCowTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17449) -ComposableCowTest:test_createAndRemove_FuzzSetAndEmit(address,address,bytes32,bytes) (runs: 256, μ: 38661, ~: 38534) -ComposableCowTest:test_createAndRemove_e2e() (gas: 466319) -ComposableCowTest:test_createWithContextAndRemove_FuzzSetAndEmit(address,address,bytes32,bytes,bytes32) (runs: 256, μ: 62829, ~: 62956) +ComposableCowTest:test_createAndRemove_FuzzSetAndEmit(address,address,bytes32,bytes) (runs: 256, μ: 38672, ~: 38543) +ComposableCowTest:test_createAndRemove_e2e() (gas: 460533) +ComposableCowTest:test_createWithContextAndRemove_FuzzSetAndEmit(address,address,bytes32,bytes,bytes32) (runs: 256, μ: 62959, ~: 62947) ComposableCowTest:test_create_RevertOnInvalidHandler() (gas: 9239) -ComposableCowTest:test_getTradeableOrderWithSignature_FuzzRevertInvalidProof(address,bytes32[],bytes32,address,bytes32,bytes) (runs: 256, μ: 103749, ~: 105293) +ComposableCowTest:test_getTradeableOrderWithSignature_FuzzRevertInvalidProof(address,bytes32[],bytes32,address,bytes32,bytes) (runs: 256, μ: 90887, ~: 91957) ComposableCowTest:test_getTradeableOrderWithSignature_FuzzRevertInvalidSingleOrder(address,address,bytes32,bytes) (runs: 256, μ: 18522, ~: 18502) -ComposableCowTest:test_getTradeableOrderWithSignature_ReturnsValidPayloadForNonSafe() (gas: 688970) -ComposableCowTest:test_getTradeableOrderWithSignature_ReturnsValidPayloadForSafe() (gas: 108337) -ComposableCowTest:test_getTradeableOrderWithSignature_RevertInterfaceNotSupported() (gas: 51007) -ComposableCowTest:test_isValidSafeSignature_BaseConditionalOrder_RevertOnInvalidHash() (gas: 59404) -ComposableCowTest:test_isValidSafeSignature_FuzzPassesContextToHandler(address,bytes32) (runs: 256, μ: 176689, ~: 176689) -ComposableCowTest:test_isValidSafeSignature_FuzzRevertInvalidProof(address,bytes32[],bytes32,address,bytes32,bytes) (runs: 256, μ: 115483, ~: 117341) -ComposableCowTest:test_isValidSafeSignature_FuzzRevertInvalidSingleOrder(address,address,bytes32,bytes) (runs: 256, μ: 18063, ~: 18036) -ComposableCowTest:test_remove_EmitsConditionalOrderRemoved() (gas: 34420) -ComposableCowTest:test_remove_FuzzEmitsEvent(address,bytes32) (runs: 256, μ: 30296, ~: 30267) +ComposableCowTest:test_getTradeableOrderWithSignature_ReturnsValidPayloadForNonSafe() (gas: 682611) +ComposableCowTest:test_getTradeableOrderWithSignature_ReturnsValidPayloadForSafe() (gas: 108293) +ComposableCowTest:test_getTradeableOrderWithSignature_RevertInterfaceNotSupported() (gas: 51029) +ComposableCowTest:test_isValidSafeSignature_BaseConditionalOrder_RevertOnInvalidHash() (gas: 59426) +ComposableCowTest:test_isValidSafeSignature_FuzzPassesContextToHandler(address,bytes32) (runs: 256, μ: 176625, ~: 176625) +ComposableCowTest:test_isValidSafeSignature_FuzzRevertInvalidProof(address,bytes32[],bytes32,address,bytes32,bytes) (runs: 256, μ: 102643, ~: 103983) +ComposableCowTest:test_isValidSafeSignature_FuzzRevertInvalidSingleOrder(address,address,bytes32,bytes) (runs: 256, μ: 18040, ~: 18014) +ComposableCowTest:test_remove_EmitsConditionalOrderRemoved() (gas: 34437) +ComposableCowTest:test_remove_FuzzEmitsEvent(address,bytes32) (runs: 256, μ: 30313, ~: 30286) ComposableCowTest:test_safeSignaturePayload_SelectorMatchesMuxerMagicValue() (gas: 311) -ComposableCowTest:test_setRootWithContext_FuzzSetAndEmit(address,bytes32,bytes32) (runs: 256, μ: 72865, ~: 72865) -ComposableCowTest:test_setRootWithContext_e2e() (gas: 13471606) +ComposableCowTest:test_setRootWithContext_FuzzSetAndEmit(address,bytes32,bytes32) (runs: 256, μ: 72842, ~: 72842) +ComposableCowTest:test_setRootWithContext_e2e() (gas: 13430581) ComposableCowTest:test_setRoot_FuzzSetAndEmit(address,bytes32) (runs: 256, μ: 41225, ~: 41225) -ComposableCowTest:test_setRoot_e2e() (gas: 13439957) -ComposableCowTwapTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10756) -ComposableCowTwapTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17516) -ComposableCowTwapTest:test_TWAPOrderMathLib_calculateValidTo(uint256,uint256,uint256,uint256,uint256) (runs: 256, μ: 11534, ~: 11180) +ComposableCowTest:test_setRoot_e2e() (gas: 13398954) +ComposableCowTwapTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10778) +ComposableCowTwapTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17494) +ComposableCowTwapTest:test_TWAPOrderMathLib_calculateValidTo(uint256,uint256,uint256,uint256,uint256) (runs: 256, μ: 11534, ~: 11298) ComposableCowTwapTest:test_describeOrder_RevertOnZeroFrequency() (gas: 20455) ComposableCowTwapTest:test_describeOrder_TwapParts() (gas: 27822) -ComposableCowTwapTest:test_generateOrder_FuzzRevertIfBeforeStart(uint256,uint256) (runs: 256, μ: 27943, ~: 27943) -ComposableCowTwapTest:test_generateOrder_FuzzRevertIfExpired(uint256,uint256) (runs: 256, μ: 28676, ~: 28421) -ComposableCowTwapTest:test_generateOrder_FuzzRevertIfOrderAfterBlocktimestampValidity(uint256,uint256) (runs: 256, μ: 177052, ~: 177675) -ComposableCowTwapTest:test_generateOrder_FuzzRevertIfOrderBeforeBlockTimestamp(uint256,uint256) (runs: 256, μ: 177662, ~: 177662) -ComposableCowTwapTest:test_generateOrder_FuzzRevertIfOutsideSpan(uint256,uint256) (runs: 256, μ: 31158, ~: 31006) -ComposableCowTwapTest:test_generateOrder_FuzzRevertOnInvalidFrequency(uint256) (runs: 256, μ: 19501, ~: 19502) -ComposableCowTwapTest:test_generateOrder_FuzzRevertOnInvalidNumParts(uint256) (runs: 256, μ: 19396, ~: 19398) -ComposableCowTwapTest:test_generateOrder_FuzzRevertOnInvalidSpan(uint256,uint256) (runs: 256, μ: 19978, ~: 19978) +ComposableCowTwapTest:test_generateOrder_FuzzRevertIfBeforeStart(uint256,uint256) (runs: 256, μ: 27962, ~: 27962) +ComposableCowTwapTest:test_generateOrder_FuzzRevertIfExpired(uint256,uint256) (runs: 256, μ: 28699, ~: 28418) +ComposableCowTwapTest:test_generateOrder_FuzzRevertIfOrderAfterBlocktimestampValidity(uint256,uint256) (runs: 256, μ: 176817, ~: 177502) +ComposableCowTwapTest:test_generateOrder_FuzzRevertIfOrderBeforeBlockTimestamp(uint256,uint256) (runs: 256, μ: 177507, ~: 177507) +ComposableCowTwapTest:test_generateOrder_FuzzRevertIfOutsideSpan(uint256,uint256) (runs: 256, μ: 31177, ~: 31000) +ComposableCowTwapTest:test_generateOrder_FuzzRevertOnInvalidFrequency(uint256) (runs: 256, μ: 19523, ~: 19524) +ComposableCowTwapTest:test_generateOrder_FuzzRevertOnInvalidNumParts(uint256) (runs: 256, μ: 19418, ~: 19420) +ComposableCowTwapTest:test_generateOrder_FuzzRevertOnInvalidSpan(uint256,uint256) (runs: 256, μ: 19911, ~: 19911) ComposableCowTwapTest:test_generateOrder_FuzzRevertOnInvalidStartTime(uint256) (runs: 256, μ: 19300, ~: 19300) -ComposableCowTwapTest:test_generateOrder_RevertOnSameTokens() (gas: 18769) -ComposableCowTwapTest:test_generateOrder_RevertOnTokenZero() (gas: 25858) -ComposableCowTwapTest:test_generateOrder_RevertOnZeroMinPartLimit() (gas: 18862) +ComposableCowTwapTest:test_generateOrder_RevertOnSameTokens() (gas: 18791) +ComposableCowTwapTest:test_generateOrder_RevertOnTokenZero() (gas: 25794) +ComposableCowTwapTest:test_generateOrder_RevertOnZeroMinPartLimit() (gas: 18795) ComposableCowTwapTest:test_generateOrder_RevertOnZeroPartSellAmount() (gas: 18760) -ComposableCowTwapTest:test_generateOrder_e2e_fuzz(uint256,uint256) (runs: 256, μ: 192836, ~: 192553) -ComposableCowTwapTest:test_generateOrder_e2e_fuzz_WithContext(uint32,uint256) (runs: 256, μ: 222852, ~: 225776) +ComposableCowTwapTest:test_generateOrder_e2e_fuzz(uint256,uint256) (runs: 256, μ: 192643, ~: 192376) +ComposableCowTwapTest:test_generateOrder_e2e_fuzz_WithContext(uint32,uint256) (runs: 256, μ: 223048, ~: 225599) ComposableCowTwapTest:test_getNextPollTimestamp_FinalPartStopsPolling() (gas: 18992) -ComposableCowTwapTest:test_getNextPollTimestamp_PointsAtNextPart() (gas: 19021) +ComposableCowTwapTest:test_getNextPollTimestamp_PointsAtNextPart() (gas: 19043) ComposableCowTwapTest:test_getNextPollTimestamp_RevertOnZeroFrequency() (gas: 18475) -ComposableCowTwapTest:test_getNextPollTimestamp_RevertOnZeroNumParts() (gas: 18360) -ComposableCowTwapTest:test_settle_e2e() (gas: 13390320) -ComposableCowTwapTest:test_simulate_fuzz(uint32,uint32,uint32) (runs: 256, μ: 19819615, ~: 20053989) -ComposableCowTwapTest:test_verify_e2e_fuzz(uint256,uint256) (runs: 256, μ: 33596, ~: 33312) \ No newline at end of file +ComposableCowTwapTest:test_getNextPollTimestamp_RevertOnZeroNumParts() (gas: 18382) +ComposableCowTwapTest:test_settle_e2e() (gas: 13350768) +ComposableCowTwapTest:test_simulate_fuzz(uint32,uint32,uint32) (runs: 256, μ: 20021414, ~: 20545024) +ComposableCowTwapTest:test_verify_e2e_fuzz(uint256,uint256) (runs: 256, μ: 33508, ~: 33239) \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 2356eb03..427e052a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,12 +2,6 @@ path = lib/forge-std url = https://github.com/foundry-rs/forge-std branch = v1.5.3 -[submodule "lib/murky"] - path = lib/murky - url = https://github.com/dmfxyz/murky -[submodule "lib/@openzeppelin"] - path = lib/@openzeppelin - url = https://github.com/openzeppelin/openzeppelin-contracts [submodule "lib/cowprotocol"] path = lib/cowprotocol url = https://github.com/cowprotocol/contracts @@ -16,3 +10,6 @@ path = lib/safe url = https://github.com/cowdao-grants/extensible-fallback-handler branch = main +[submodule "lib/solady"] + path = lib/solady + url = https://github.com/vectorized/solady diff --git a/docs/discovery.md b/docs/discovery.md index b7529560..cb7fc27e 100644 --- a/docs/discovery.md +++ b/docs/discovery.md @@ -639,7 +639,7 @@ recomputing the root. - `leafEncoding: "v1"` pins the full tree construction, byte-exact against `_auth`: `leaf = keccak256(abi.encode(ConditionalOrderParams))`; the tree is built bottom-up over the ascending-sorted leaf array; each internal node is - `keccak256(sorted-pair(a, b))` (OpenZeppelin `MerkleProof` convention); an + `keccak256(sorted-pair(a, b))`; an odd trailing node at any level is promoted unchanged to the next level. Sorted-pair hashing alone does not determine tree shape — implementations MUST follow this construction (note: OpenZeppelin's `StandardMerkleTree` diff --git a/foundry.lock b/foundry.lock index 5d1e3430..4db6ceeb 100644 --- a/foundry.lock +++ b/foundry.lock @@ -1,7 +1,4 @@ { - "lib/@openzeppelin": { - "rev": "fd81a96f01cc42ef1c9a5399364968d0e07e9e90" - }, "lib/cowprotocol": { "branch": { "name": "main", @@ -14,13 +11,16 @@ "rev": "73a504d2cf6f37b7ce285b479f4c681f76e95f1b" } }, - "lib/murky": { - "rev": "1d9566b908b9702c45d354a1caabe8ef5a69938d" - }, "lib/safe": { "branch": { "name": "main", "rev": "11273c1f08eda18ed8ff49ec1d4abec5e451ff21" } + }, + "lib/solady": { + "tag": { + "name": "v0.1.26", + "rev": "acd959aa4bd04720d640bf4e6a5c71037510cc4b" + } } -} \ No newline at end of file +} diff --git a/lib/@openzeppelin b/lib/@openzeppelin deleted file mode 160000 index fd81a96f..00000000 --- a/lib/@openzeppelin +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fd81a96f01cc42ef1c9a5399364968d0e07e9e90 diff --git a/lib/murky b/lib/murky deleted file mode 160000 index 1d9566b9..00000000 --- a/lib/murky +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1d9566b908b9702c45d354a1caabe8ef5a69938d diff --git a/lib/solady b/lib/solady new file mode 160000 index 00000000..acd959aa --- /dev/null +++ b/lib/solady @@ -0,0 +1 @@ +Subproject commit acd959aa4bd04720d640bf4e6a5c71037510cc4b diff --git a/remappings.txt b/remappings.txt index 446970f0..bf08ef8c 100644 --- a/remappings.txt +++ b/remappings.txt @@ -1,7 +1,5 @@ -@openzeppelin/=lib/@openzeppelin/ +cowprotocol/=lib/cowprotocol/src/ ds-test/=lib/forge-std/lib/ds-test/src/ -erc4626-tests/=lib/@openzeppelin/lib/erc4626-tests/ forge-std/=lib/forge-std/src/ -murky/=lib/murky/src/ -openzeppelin-contracts/=lib/murky/lib/openzeppelin-contracts/ safe/=lib/safe/contracts/ +solady/=lib/solady/src/ diff --git a/src/ComposableCow.sol b/src/ComposableCow.sol index f368bb46..b33bec16 100644 --- a/src/ComposableCow.sol +++ b/src/ComposableCow.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; +import {MerkleProofLib} from "solady/utils/MerkleProofLib.sol"; import { ExtensibleFallbackHandler, ERC1271, @@ -521,7 +521,7 @@ contract ComposableCow is ISafeSignatureVerifier { if (proof.length != 0) { // The order is part of a merkle tree bytes32 leaf = keccak256(bytes.concat(hash(params))); - require(MerkleProof.verify(proof, roots[owner], leaf), ProofNotAuthed()); + require(MerkleProofLib.verify(proof, roots[owner], leaf), ProofNotAuthed()); } else { // The order is a single order ctx = hash(params); diff --git a/src/types/GoodAfterTime.sol b/src/types/GoodAfterTime.sol index df097942..1b13aa26 100644 --- a/src/types/GoodAfterTime.sol +++ b/src/types/GoodAfterTime.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; +import {SafeCastLib} from "solady/utils/SafeCastLib.sol"; import {IExpectedOutCalculator} from "../vendored/Milkman.sol"; import { @@ -50,7 +50,7 @@ contract GoodAfterTime is OrderDescriptor { OrderDescriptor(descriptorUris, descriptorDigest_, descriptorKind) {} - using SafeCast for uint256; + using SafeCastLib for uint256; // --- types diff --git a/src/types/twap/TWAP.sol b/src/types/twap/TWAP.sol index 4e023df1..c88da651 100644 --- a/src/types/twap/TWAP.sol +++ b/src/types/twap/TWAP.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; +import {SafeCastLib} from "solady/utils/SafeCastLib.sol"; import {ComposableCow} from "../../ComposableCow.sol"; @@ -37,7 +37,7 @@ error OrderNotInitialized(); * @dev Designed to be used with the CoW Protocol Conditional Order Framework. */ contract TWAP is OrderDescriptor { - using SafeCast for uint256; + using SafeCastLib for uint256; ComposableCow public immutable composableCow; diff --git a/src/types/twap/libraries/TWAPOrder.sol b/src/types/twap/libraries/TWAPOrder.sol index d90c82b0..825f6e85 100644 --- a/src/types/twap/libraries/TWAPOrder.sol +++ b/src/types/twap/libraries/TWAPOrder.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; +import {SafeCastLib} from "solady/utils/SafeCastLib.sol"; import {IERC20, GPv2Order} from "cowprotocol/contracts/libraries/GPv2Order.sol"; import {IConditionalOrder} from "../../../interfaces/IConditionalOrder.sol"; @@ -48,7 +48,7 @@ error InvalidSpan(); * @dev Structs, errors, and functions for time-weighted average orders. */ library TWAPOrder { - using SafeCast for uint256; + using SafeCastLib for uint256; // --- structs diff --git a/test/ComposableCow.base.t.sol b/test/ComposableCow.base.t.sol index ba4d3589..44838d7e 100644 --- a/test/ComposableCow.base.t.sol +++ b/test/ComposableCow.base.t.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -import {Merkle} from "murky/Merkle.sol"; - import {Safe, IERC165, Enum} from "safe/Safe.sol"; // Testing Libraries @@ -30,7 +28,7 @@ import {IValueFactory} from "../src/interfaces/IValueFactory.sol"; import {ISwapGuard, ComposableCow, GPv2Order} from "../src/ComposableCow.sol"; import {PackageKind} from "../src/interfaces/PackageKind.sol"; -contract BaseComposableCowTest is Base, Merkle { +contract BaseComposableCowTest is Base { using ComposableCowLib for IConditionalOrder.ConditionalOrderParams; using SafeLib for Safe; diff --git a/test/ComposableCow.proof.t.sol b/test/ComposableCow.proof.t.sol index b0b15403..0842d6fa 100644 --- a/test/ComposableCow.proof.t.sol +++ b/test/ComposableCow.proof.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; +import {MerkleProofLib} from "solady/utils/MerkleProofLib.sol"; import {IConditionalOrder, ComposableCow, BaseComposableCowTest} from "./ComposableCow.base.t.sol"; import {ComposableCowLib} from "./libraries/ComposableCowLib.t.sol"; @@ -163,7 +163,7 @@ contract ComposableCowProofTest is BaseComposableCowTest { /** * @dev The payload standard's tree construction, implemented - * independently of the Murky test helper: ascending-sorted leaf + * independently of solady's `MerkleTreeLib`: ascending-sorted leaf * hashes, bottom-up sorted-pair keccak, odd trailing node promoted * unchanged. Mutates `hashes` in place. */ @@ -245,7 +245,7 @@ contract ComposableCowProofTest is BaseComposableCowTest { /** * @dev The normative construction (`leafEncoding: "v1"`) is verifiable by - * exactly the check `_auth` performs (OZ `MerkleProof.verify`), for + * exactly the check `_auth` performs (`MerkleProofLib.verify`), for * every leaf across minimal, even, and odd tree sizes - including * the odd-promotion levels */ @@ -272,7 +272,9 @@ contract ComposableCowProofTest is BaseComposableCowTest { } bytes32[] memory proof = _normativeProof(forProof, leaf); // the exact check _auth performs - assertTrue(MerkleProof.verify(proof, root, leaf), "normative proof rejected by OZ verify"); + assertTrue( + MerkleProofLib.verify(proof, root, leaf), "normative proof rejected by MerkleProofLib.verify" + ); } } } diff --git a/test/ComposableCow.t.sol b/test/ComposableCow.t.sol index f3674ada..d9ca1a9d 100644 --- a/test/ComposableCow.t.sol +++ b/test/ComposableCow.t.sol @@ -51,7 +51,7 @@ contract ComposableCowTest is BaseComposableCowTest { function test_setRoot_e2e() public { IConditionalOrder.ConditionalOrderParams[] memory _leaves = getBundle(safe1, 50); (bytes32 root, bytes32[] memory proof, IConditionalOrder.ConditionalOrderParams memory params) = - _leaves.getRootAndProof(0, leaves, getRoot, getProof); + _leaves.getRootAndProof(0, leaves); // should fail to validate the proof as root is still set bytes32(0) vm.expectRevert(ComposableCow.ProofNotAuthed.selector); @@ -95,7 +95,7 @@ contract ComposableCowTest is BaseComposableCowTest { function test_setRootWithContext_e2e() public { IConditionalOrder.ConditionalOrderParams[] memory _leaves = getBundle(safe1, 50); (bytes32 root, bytes32[] memory proof, IConditionalOrder.ConditionalOrderParams memory params) = - _leaves.getRootAndProof(0, leaves, getRoot, getProof); + _leaves.getRootAndProof(0, leaves); // should fail to validate the proof as root is still set bytes32(0) vm.expectRevert(ComposableCow.ProofNotAuthed.selector); diff --git a/test/ComposableCow.twap.t.sol b/test/ComposableCow.twap.t.sol index 93d65e10..84133562 100644 --- a/test/ComposableCow.twap.t.sol +++ b/test/ComposableCow.twap.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; +import {SafeCastLib} from "solady/utils/SafeCastLib.sol"; import {ERC1271} from "safe/handler/extensible/SignatureVerifierMuxer.sol"; import {IConditionalOrderGenerator} from "../src/interfaces/IConditionalOrder.sol"; @@ -487,7 +487,7 @@ contract ComposableCowTwapTest is BaseComposableCowTest { // 2. Do the merkle tree dance (bytes32 root, bytes32[] memory proof, IConditionalOrder.ConditionalOrderParams memory leaf) = - _leaves.getRootAndProof(0, leaves, getRoot, getProof); + _leaves.getRootAndProof(0, leaves); // 3. Set the root _setRoot( diff --git a/test/helpers/Tokens.t.sol b/test/helpers/Tokens.t.sol index 55d1feb1..634a9270 100644 --- a/test/helpers/Tokens.t.sol +++ b/test/helpers/Tokens.t.sol @@ -2,20 +2,34 @@ pragma solidity >=0.8.0 <0.9.0; import {IERC20} from "cowprotocol/contracts/interfaces/IERC20.sol"; -import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import {ERC20} from "solady/tokens/ERC20.sol"; /** * @title Mock ERC20 token for testing. * @author mfw78 */ contract MockERC20 is ERC20 { + string private _name; + string private _symbol; + /** * @dev Initializes a new mock ERC20 token. No tokens are minted, makes use instead * of `vm.deal` in tests. - * @param name The name of the token. - * @param symbol The symbol of the token. + * @param name_ The name of the token. + * @param symbol_ The symbol of the token. */ - constructor(string memory name, string memory symbol) ERC20(name, symbol) {} + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + function name() public view override returns (string memory) { + return _name; + } + + function symbol() public view override returns (string memory) { + return _symbol; + } } /** diff --git a/test/libraries/ComposableCowLib.t.sol b/test/libraries/ComposableCowLib.t.sol index 7a6d52c4..6d4a514a 100644 --- a/test/libraries/ComposableCowLib.t.sol +++ b/test/libraries/ComposableCowLib.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -import {Merkle} from "murky/Merkle.sol"; +import {MerkleTreeLib} from "solady/utils/MerkleTreeLib.sol"; import {IConditionalOrder} from "../../src/interfaces/IConditionalOrder.sol"; library ComposableCowLib { @@ -27,8 +27,6 @@ library ComposableCowLib { * @param leaves to be inserted into the tree * @param n th leaf to generate the proof for * @param m a mapping of hashes to leaves to be populated (storage) - * @param getRoot a function that returns the root of the tree given an array of hashes - * @param getProof a function that returns the proof for a leaf given an array of hashes and the index of the leaf * @return the root of the tree * @return a proof for the n'th leaf * @return the n'th leaf @@ -36,9 +34,7 @@ library ComposableCowLib { function getRootAndProof( IConditionalOrder.ConditionalOrderParams[] memory leaves, uint256 n, - mapping(bytes32 => IConditionalOrder.ConditionalOrderParams) storage m, - function(bytes32[] memory) internal pure returns (bytes32) getRoot, - function(bytes32[] memory, uint256) internal pure returns (bytes32[] memory) getProof + mapping(bytes32 => IConditionalOrder.ConditionalOrderParams) storage m ) internal returns (bytes32, bytes32[] memory, IConditionalOrder.ConditionalOrderParams memory) { // 1. Create a mapping of hashes to leaves for (uint256 i = 0; i < leaves.length; i++) { @@ -54,11 +50,13 @@ library ComposableCowLib { // 3. Sort the hashes bytes32[] memory sortedHashes = sort(hashes); - // 4. Create the Merkle root - bytes32 root = getRoot(sortedHashes); - - // 5. Create the Merkle proof for the n'th leaf - bytes32[] memory proof = getProof(sortedHashes, n); + // 4. Build the tree, then take the root and the n'th leaf's proof. + // `MerkleTreeLib` pairs with `MerkleProofLib`, which is what + // `ComposableCow` verifies with, so construction and verification + // come from the same family. + bytes32[] memory tree = MerkleTreeLib.build(sortedHashes); + bytes32 root = MerkleTreeLib.root(tree); + bytes32[] memory proof = MerkleTreeLib.leafProof(tree, n); // 6. Get the leaf that was used to create the proof IConditionalOrder.ConditionalOrderParams memory leaf = m[sortedHashes[n]]; diff --git a/test/vendored/GPv2TradeEncoder.sol b/test/vendored/GPv2TradeEncoder.sol index 346b15d5..6c2751eb 100644 --- a/test/vendored/GPv2TradeEncoder.sol +++ b/test/vendored/GPv2TradeEncoder.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; +import {IERC20} from "cowprotocol/contracts/interfaces/IERC20.sol"; import {GPv2Order} from "cowprotocol/contracts/libraries/GPv2Order.sol"; import {GPv2Signing} from "cowprotocol/contracts/mixins/GPv2Signing.sol";