From 63c7d6b1ae6a40172117e2a6a8a52a12c594de6a Mon Sep 17 00:00:00 2001 From: mfw78 Date: Sun, 2 Aug 2026 23:11:07 +0000 Subject: [PATCH 1/4] build!: vendor the Safe interfaces and build deployment bytecode with via_ir `src` no longer depends on `safe-contracts`. The six symbols it used are vendored into `src/vendor/Safe.sol`, declared identically so a contract written against either compiles against this. The dependency was a compilation liability rather than a design one. `Safe.sol` uses inline assembly that is not annotated memory-safe, so the IR pipeline cannot allocate its stack and `via_ir` fails on the whole project. Nothing in `src` needed the implementation: `Safe` is only ever a typed address, since `isValidSafeSignature` takes one as a parameter and `_auth` reads this registry's own `roots` and `singleOrders`. `ExtensibleFallbackHandler` is not vendored at all; it was only ever asked `supportsInterface`, so `IERC165` says the same thing. With `src` clean, `via_ir` compiles, and the deployed bytecode is smaller: TWAP 12,629 -> 11,483 -9.1% GoodAfterTime 9,870 -> 9,024 -8.6% TradeAboveThreshold 7,844 -> 7,194 -8.3% StopLoss 10,183 -> 9,360 -8.1% OwnedTWAP 15,478 -> 14,316 -7.5% ComposableCow 10,659 -> 10,047 -5.7% It cannot be the default profile. The tests and the four Safe-side deploy scripts still link `safe-contracts`, deliberately: they are the only thing proving the `ExtensibleFallbackHandler` and `domainVerifier` path works, which is the integration this registry primarily exists to serve. Mocking that would test the mock. So `[profile.prod]` carries `via_ir` and skips them, and CI builds it alongside the normal one so the two cannot diverge unnoticed. Whatever is deployed must come from `FOUNDRY_PROFILE=prod`. The gas snapshot, the descriptors and the test suite all run against the legacy build. Tests keep the real `Safe` for fixtures and use the vendored type only where they call into the registry, which is the one place the two meet. --- .github/workflows/test.yml | 6 +++ foundry.toml | 13 +++++++ src/ComposableCow.sol | 13 ++----- src/ERC1271Forwarder.sol | 2 +- src/interfaces/IConditionalOrder.sol | 2 +- src/interfaces/ISwapGuard.sol | 2 +- src/vendor/Safe.sol | 55 ++++++++++++++++++++++++++++ test/ComposableCow.t.sol | 9 +++-- 8 files changed, 85 insertions(+), 17 deletions(-) create mode 100644 src/vendor/Safe.sol diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 03cbea55..557cae57 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -57,3 +57,9 @@ jobs: # `fork` needs an archive-node RPC and is not run here. The fuzz seed is # pinned so a failure is reproducible from the log alone. run: forge test -vvv --no-match-test "fork" --fuzz-seed 672679878 + + # Deployed bytecode is built with via_ir, which the default profile cannot + # use while the Safe dependency is still linked into the tests and the + # Safe-side scripts. Building it here stops the two diverging unnoticed. + - name: Build deployment bytecode (via_ir) + run: FOUNDRY_PROFILE=prod forge build diff --git a/foundry.toml b/foundry.toml index b7201f30..8ee941d0 100644 --- a/foundry.toml +++ b/foundry.toml @@ -19,5 +19,18 @@ targets = [ ] timeout = 100000 +# Deployed bytecode. via_ir cannot be the default: the Safe dependency that the +# tests and the Safe-side deploy scripts still use has inline assembly that is +# not annotated memory-safe, so the IR pipeline cannot allocate its stack. +[profile.prod] +via_ir = true +skip = [ + 'test/**', + 'script/deploy_ProdStack.s.sol', + 'script/deploy_AnvilStack.s.sol', + 'script/deploy_ExtensibleFallbackHandler.s.sol', + 'script/submit_SingleOrder.s.sol', +] + [profile.ci] verbosity = 3 \ No newline at end of file diff --git a/src/ComposableCow.sol b/src/ComposableCow.sol index b33bec16..991c8463 100644 --- a/src/ComposableCow.sol +++ b/src/ComposableCow.sol @@ -2,13 +2,8 @@ pragma solidity >=0.8.0 <0.9.0; import {MerkleProofLib} from "solady/utils/MerkleProofLib.sol"; -import { - ExtensibleFallbackHandler, - ERC1271, - ISignatureVerifierMuxer, - ISafeSignatureVerifier, - Safe -} from "safe/handler/ExtensibleFallbackHandler.sol"; + +import {IERC165, ERC1271, ISignatureVerifierMuxer, ISafeSignatureVerifier, Safe} from "./vendor/Safe.sol"; import {IConditionalOrder, IConditionalOrderGenerator, GPv2Order} from "./interfaces/IConditionalOrder.sol"; import {ISwapGuard} from "./interfaces/ISwapGuard.sol"; @@ -557,9 +552,7 @@ contract ComposableCow is ISafeSignatureVerifier { GPv2Order.Data memory order ) internal view returns (bytes memory signature) { // Get the signature for the order - try ExtensibleFallbackHandler(owner).supportsInterface(type(ISignatureVerifierMuxer).interfaceId) returns ( - bool supported - ) { + try IERC165(owner).supportsInterface(type(ISignatureVerifierMuxer).interfaceId) returns (bool supported) { if (!supported) { revert InvalidFallbackHandler(); } diff --git a/src/ERC1271Forwarder.sol b/src/ERC1271Forwarder.sol index 6a1a2055..d90a7cae 100644 --- a/src/ERC1271Forwarder.sol +++ b/src/ERC1271Forwarder.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -import {ERC1271, Safe} from "safe/handler/extensible/SignatureVerifierMuxer.sol"; +import {ERC1271, Safe} from "./vendor/Safe.sol"; import {GPv2Order} from "cowprotocol/contracts/libraries/GPv2Order.sol"; import {ComposableCow} from "./ComposableCow.sol"; diff --git a/src/interfaces/IConditionalOrder.sol b/src/interfaces/IConditionalOrder.sol index ca850f5a..d7704437 100644 --- a/src/interfaces/IConditionalOrder.sol +++ b/src/interfaces/IConditionalOrder.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.0 <0.9.0; import {GPv2Order} from "cowprotocol/contracts/libraries/GPv2Order.sol"; -import {IERC165} from "safe/interfaces/IERC165.sol"; +import {IERC165} from "../vendor/Safe.sol"; /** * @dev Canonical reason for `PollNeedsOffchainInput`: the handler cannot diff --git a/src/interfaces/ISwapGuard.sol b/src/interfaces/ISwapGuard.sol index a0a84837..b6816277 100644 --- a/src/interfaces/ISwapGuard.sol +++ b/src/interfaces/ISwapGuard.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -import {IERC165} from "safe/interfaces/IERC165.sol"; +import {IERC165} from "../vendor/Safe.sol"; import {IConditionalOrder, GPv2Order} from "./IConditionalOrder.sol"; diff --git a/src/vendor/Safe.sol b/src/vendor/Safe.sol new file mode 100644 index 00000000..d0e02993 --- /dev/null +++ b/src/vendor/Safe.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +/** + * @dev The Safe surface this registry actually uses, vendored from + * `safe-contracts` rather than depended upon. + * + * The dependency was a compilation liability: `Safe.sol` uses inline + * assembly that is not annotated memory-safe, so the IR pipeline cannot + * allocate its stack and `via_ir` fails on the whole project. Nothing here + * needs the implementation. `Safe` is only ever a typed address, and the + * handler is only ever asked whether it supports an interface. + * + * Declarations match `safe-contracts` exactly, so a contract written + * against either compiles against this. + */ + +/// @dev Standard ERC-165. +interface IERC165 { + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} + +/// @dev ERC-1271, as `safe-contracts` declares it. +interface ERC1271 { + function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4 magicValue); +} + +/** + * @dev A Safe, as far as this registry is concerned. Only its address is used: + * `isValidSafeSignature` takes one as a typed address and `_auth` reads + * the registry's own storage, so no Safe behaviour is invoked. + */ +interface Safe {} + +/** + * @title Safe Signature Verifier Interface + * @notice Standard for external contracts verifying signatures for a Safe. + */ +interface ISafeSignatureVerifier { + function isValidSafeSignature( + Safe safe, + address sender, + bytes32 _hash, + bytes32 domainSeparator, + bytes32 typeHash, + bytes calldata encodeData, + bytes calldata payload + ) external view returns (bytes4 magic); +} + +interface ISignatureVerifierMuxer { + function domainVerifiers(Safe safe, bytes32 domainSeparator) external view returns (ISafeSignatureVerifier); + + function setDomainVerifier(bytes32 domainSeparator, ISafeSignatureVerifier verifier) external; +} diff --git a/test/ComposableCow.t.sol b/test/ComposableCow.t.sol index d9ca1a9d..a3dc86e0 100644 --- a/test/ComposableCow.t.sol +++ b/test/ComposableCow.t.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; +import {Safe as CowSafe} from "../src/vendor/Safe.sol"; import {ERC1271} from "safe/handler/extensible/SignatureVerifierMuxer.sol"; import {ISafeSignaturePayload} from "../src/ComposableCow.sol"; @@ -262,7 +263,7 @@ contract ComposableCowTest is BaseComposableCowTest { // should revert as the order hash mismatches vm.expectRevert(abi.encodeWithSelector(IConditionalOrder.OrderNotValid.selector, InvalidHash.selector)); composableCow.isValidSafeSignature( - Safe(payable(address(alice.addr))), + CowSafe(payable(address(alice.addr))), address(0), GPv2Order.hash(order1, domainSeparator), domainSeparator, @@ -300,7 +301,7 @@ contract ComposableCowTest is BaseComposableCowTest { // should revert as the proof is invalid vm.expectRevert(ComposableCow.ProofNotAuthed.selector); composableCow.isValidSafeSignature( - Safe(payable(owner)), + CowSafe(payable(owner)), address(0), // sender isn't used keccak256("some GPv2Order hash"), keccak256("some domain separator"), @@ -328,7 +329,7 @@ contract ComposableCowTest is BaseComposableCowTest { // should revert as the order has not been created vm.expectRevert(ComposableCow.SingleOrderNotAuthed.selector); composableCow.isValidSafeSignature( - Safe(payable(owner)), + CowSafe(payable(owner)), address(0), // sender isn't used keccak256("some gpv2order hash"), keccak256("some domain separator"), @@ -359,7 +360,7 @@ contract ComposableCowTest is BaseComposableCowTest { bytes memory cd = abi.encodeCall( composableCow.isValidSafeSignature, ( - Safe(payable(address(owner))), + CowSafe(payable(address(owner))), address(0), // sender isn't used keccak256(abi.encode(order)), domainSeparator, From 3b85ef128f0c0b4c0e35b793f7d96f7f7a716f10 Mon Sep 17 00:00:00 2001 From: mfw78 Date: Mon, 3 Aug 2026 00:05:58 +0000 Subject: [PATCH 2/4] build!: upstream Safe v1.5.0, forge-std v1.11.0, via_ir everywhere Replaces the two-profile split from the previous commit. `via_ir` is now the default, so the tests, the gas snapshot, the descriptors and whatever gets deployed all run against the same bytecode. Maintaining two was a footgun. Three things blocked it, and each turned out to be a dependency rather than our code: - `src` imported the Safe fork. Fixed in the previous commit by vendoring the six interfaces it used. - `lib/safe` was `cowdao-grants/extensible-fallback-handler`, pinned by commit on `main`, whose `Safe.sol` uses inline assembly that is not annotated memory-safe, so the IR pipeline cannot allocate its stack. It is now `safe-global/safe-smart-account` at tag `v1.5.0`, where every assembly block in `Safe.sol` is `assembly ("memory-safe")`. Upstream absorbed the `ExtensibleFallbackHandler` work, so nothing is lost by leaving the fork. - `forge-std` v1.5.1's `StdStorage.find` hit the same stack limit, and `forge-std` reaches every test through `Test.sol`. Bumped to v1.11.0. The Safe bump is not source compatible. `Enum` moved to `libraries/`, `MarshalLib` is no longer re-exported from `ExtensibleFallbackHandler.sol`, and `Safe.sol` no longer re-exports `IERC165` or `Enum`. One import in `deploy_ProdStack` also reached into `../lib/safe/contracts/...` directly, bypassing the remapping, which is why the fork kept being compiled no matter what `safe/` pointed at. One behavioural difference is accepted knowingly. The fork replaced the manual calldata offsets in `SignatureVerifierMuxer` with a single `abi.decode`; upstream v1.5.0 still computes offsets by hand. Moving upstream reverts that. The other two fork commits do not matter: the `ExtensibleBase` rename is present upstream, and the remaining one only corrects a comment. `forge-std` v1.11.0 declares `parseJsonKeys`, so the local interface in the descriptor test is gone. `getRootAndProof` merges its two loops and scopes its intermediates. That was an attempt to fix the stack error before the real cause was found, and is kept only because it reads better. 182 tests pass, formatting is clean, descriptors are current, and the whole project compiles under `via_ir`. --- .github/workflows/test.yml | 5 ----- .gitmodules | 6 +++--- foundry.lock | 8 ++++---- foundry.toml | 14 +------------- lib/forge-std | 2 +- lib/safe | 2 +- script/deploy_AnvilStack.s.sol | 2 +- script/deploy_ProdStack.s.sol | 2 +- script/submit_SingleOrder.s.sol | 2 +- test/ComposableCow.base.t.sol | 4 +++- test/ComposableCow.descriptorDoc.t.sol | 11 +---------- test/helpers/Safe.t.sol | 5 +++-- test/libraries/SafeLib.t.sol | 2 +- 13 files changed, 21 insertions(+), 44 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 557cae57..376baa7b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -58,8 +58,3 @@ jobs: # pinned so a failure is reproducible from the log alone. run: forge test -vvv --no-match-test "fork" --fuzz-seed 672679878 - # Deployed bytecode is built with via_ir, which the default profile cannot - # use while the Safe dependency is still linked into the tests and the - # Safe-side scripts. Building it here stops the two diverging unnoticed. - - name: Build deployment bytecode (via_ir) - run: FOUNDRY_PROFILE=prod forge build diff --git a/.gitmodules b/.gitmodules index 427e052a..2650fb8a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,15 +1,15 @@ [submodule "lib/forge-std"] path = lib/forge-std url = https://github.com/foundry-rs/forge-std - branch = v1.5.3 + branch = v1.11.0 [submodule "lib/cowprotocol"] path = lib/cowprotocol url = https://github.com/cowprotocol/contracts branch = main [submodule "lib/safe"] path = lib/safe - url = https://github.com/cowdao-grants/extensible-fallback-handler - branch = main + url = https://github.com/safe-global/safe-smart-account + branch = v1.5.0 [submodule "lib/solady"] path = lib/solady url = https://github.com/vectorized/solady diff --git a/foundry.lock b/foundry.lock index 4db6ceeb..17237e3f 100644 --- a/foundry.lock +++ b/foundry.lock @@ -7,14 +7,14 @@ }, "lib/forge-std": { "branch": { - "name": "v1.5.3", - "rev": "73a504d2cf6f37b7ce285b479f4c681f76e95f1b" + "name": "v1.11.0", + "rev": "8e40513d678f392f398620b3ef2b418648b33e89" } }, "lib/safe": { "branch": { - "name": "main", - "rev": "11273c1f08eda18ed8ff49ec1d4abec5e451ff21" + "name": "v1.5.0", + "rev": "dc437e8fba8b4805d76bcbd1c668c9fd3d1e83be" } }, "lib/solady": { diff --git a/foundry.toml b/foundry.toml index 8ee941d0..54bd15d2 100644 --- a/foundry.toml +++ b/foundry.toml @@ -7,6 +7,7 @@ solc_version = "0.8.30" evm_version = "cancun" optimizer = true optimizer_runs = 20000 +via_ir = true # Descriptor documents are read by test/ComposableCow.descriptorDoc.t.sol fs_permissions = [{ access = "read", path = "./descriptors" }] @@ -19,18 +20,5 @@ targets = [ ] timeout = 100000 -# Deployed bytecode. via_ir cannot be the default: the Safe dependency that the -# tests and the Safe-side deploy scripts still use has inline assembly that is -# not annotated memory-safe, so the IR pipeline cannot allocate its stack. -[profile.prod] -via_ir = true -skip = [ - 'test/**', - 'script/deploy_ProdStack.s.sol', - 'script/deploy_AnvilStack.s.sol', - 'script/deploy_ExtensibleFallbackHandler.s.sol', - 'script/submit_SingleOrder.s.sol', -] - [profile.ci] verbosity = 3 \ No newline at end of file diff --git a/lib/forge-std b/lib/forge-std index 73a504d2..8e40513d 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 73a504d2cf6f37b7ce285b479f4c681f76e95f1b +Subproject commit 8e40513d678f392f398620b3ef2b418648b33e89 diff --git a/lib/safe b/lib/safe index 11273c1f..dc437e8f 160000 --- a/lib/safe +++ b/lib/safe @@ -1 +1 @@ -Subproject commit 11273c1f08eda18ed8ff49ec1d4abec5e451ff21 +Subproject commit dc437e8fba8b4805d76bcbd1c668c9fd3d1e83be diff --git a/script/deploy_AnvilStack.s.sol b/script/deploy_AnvilStack.s.sol index 21975d27..9dac18e4 100644 --- a/script/deploy_AnvilStack.s.sol +++ b/script/deploy_AnvilStack.s.sol @@ -11,7 +11,7 @@ import {GPv2Authentication} from "cowprotocol/contracts/interfaces/GPv2Authentic // Safe contracts import {Safe} from "safe/Safe.sol"; -import {Enum} from "safe/common/Enum.sol"; +import {Enum} from "safe/libraries/Enum.sol"; import {SafeProxyFactory, SafeProxy} from "safe/proxies/SafeProxyFactory.sol"; import {CompatibilityFallbackHandler} from "safe/handler/CompatibilityFallbackHandler.sol"; import {MultiSend} from "safe/libraries/MultiSend.sol"; diff --git a/script/deploy_ProdStack.s.sol b/script/deploy_ProdStack.s.sol index b64d05a2..3f1eae7a 100644 --- a/script/deploy_ProdStack.s.sol +++ b/script/deploy_ProdStack.s.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.0 <0.9.0; import {Script} from "forge-std/Script.sol"; // ExtensibleFallbackHandler -import {ExtensibleFallbackHandler} from "../lib/safe/contracts/handler/ExtensibleFallbackHandler.sol"; +import {ExtensibleFallbackHandler} from "safe/handler/ExtensibleFallbackHandler.sol"; // ComposableCow import {ComposableCow} from "../src/ComposableCow.sol"; diff --git a/script/submit_SingleOrder.s.sol b/script/submit_SingleOrder.s.sol index 380215c9..64555286 100644 --- a/script/submit_SingleOrder.s.sol +++ b/script/submit_SingleOrder.s.sol @@ -7,7 +7,7 @@ import {IERC20} from "cowprotocol/contracts/interfaces/IERC20.sol"; // Safe contracts import {Safe} from "safe/Safe.sol"; -import {Enum} from "safe/common/Enum.sol"; +import {Enum} from "safe/libraries/Enum.sol"; import {SafeProxyFactory} from "safe/proxies/SafeProxyFactory.sol"; import {CompatibilityFallbackHandler} from "safe/handler/CompatibilityFallbackHandler.sol"; import {MultiSend} from "safe/libraries/MultiSend.sol"; diff --git a/test/ComposableCow.base.t.sol b/test/ComposableCow.base.t.sol index 44838d7e..b3b86cc8 100644 --- a/test/ComposableCow.base.t.sol +++ b/test/ComposableCow.base.t.sol @@ -1,7 +1,9 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -import {Safe, IERC165, Enum} from "safe/Safe.sol"; +import {Safe} from "safe/Safe.sol"; +import {Enum} from "safe/libraries/Enum.sol"; +import {IERC165} from "safe/interfaces/IERC165.sol"; // Testing Libraries import {Base} from "./Base.t.sol"; diff --git a/test/ComposableCow.descriptorDoc.t.sol b/test/ComposableCow.descriptorDoc.t.sol index ae2770a6..bc03e867 100644 --- a/test/ComposableCow.descriptorDoc.t.sol +++ b/test/ComposableCow.descriptorDoc.t.sol @@ -6,15 +6,6 @@ import "./ComposableCow.base.t.sol"; import "../src/types/TradeAboveThreshold.sol"; import {TWAPOrder} from "../src/types/twap/libraries/TWAPOrder.sol"; -/** - * @dev `parseJsonKeys` is supported by the `forge` binary but absent from the - * vendored `forge-std` interface, so it is declared here rather than - * bumping the submodule for one cheatcode. - */ -interface VmJson { - function parseJsonKeys(string calldata json, string calldata key) external pure returns (string[] memory); -} - /** * @dev Checks the generated descriptor documents against the contracts they * describe. Solidity rather than a JS toolchain: the facts worth @@ -45,7 +36,7 @@ contract ComposableCowDescriptorDocTest is BaseComposableCowTest { } function _errorKeys(string memory doc) private pure returns (string[] memory) { - return VmJson(address(vm)).parseJsonKeys(doc, "$.errors"); + return vm.parseJsonKeys(doc, "$.errors"); } function _hex4(bytes4 sel) private pure returns (string memory) { diff --git a/test/helpers/Safe.t.sol b/test/helpers/Safe.t.sol index ee7c42df..f551a466 100644 --- a/test/helpers/Safe.t.sol +++ b/test/helpers/Safe.t.sol @@ -2,12 +2,13 @@ pragma solidity >=0.8.0 <0.9.0; import {Safe} from "safe/Safe.sol"; -import {Enum} from "safe/common/Enum.sol"; +import {Enum} from "safe/libraries/Enum.sol"; import {SafeProxyFactory} from "safe/proxies/SafeProxyFactory.sol"; import {CompatibilityFallbackHandler} from "safe/handler/CompatibilityFallbackHandler.sol"; import {MultiSend} from "safe/libraries/MultiSend.sol"; import {SignMessageLib} from "safe/libraries/SignMessageLib.sol"; -import {ExtensibleFallbackHandler, FallbackHandler, MarshalLib} from "safe/handler/ExtensibleFallbackHandler.sol"; +import {ExtensibleFallbackHandler, FallbackHandler} from "safe/handler/ExtensibleFallbackHandler.sol"; +import {MarshalLib} from "safe/handler/extensible/MarshalLib.sol"; import {SafeLib} from "../libraries/SafeLib.t.sol"; import {TestAccount, TestAccountLib} from "../libraries/TestAccountLib.t.sol"; diff --git a/test/libraries/SafeLib.t.sol b/test/libraries/SafeLib.t.sol index 0cca03e9..e0e7950c 100644 --- a/test/libraries/SafeLib.t.sol +++ b/test/libraries/SafeLib.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -import {Enum} from "safe/common/Enum.sol"; +import {Enum} from "safe/libraries/Enum.sol"; import {Safe} from "safe/Safe.sol"; import {SafeProxy} from "safe/proxies/SafeProxy.sol"; import {SafeProxyFactory} from "safe/proxies/SafeProxyFactory.sol"; From 5218889f18a1687ee1e35307b886b2ebe5bb2c36 Mon Sep 17 00:00:00 2001 From: mfw78 Date: Mon, 3 Aug 2026 00:17:25 +0000 Subject: [PATCH 3/4] chore: regenerate the gas snapshot Kept separate from the build change so that diff stays readable, because every one of the 122 shared entries moved. The delta conflates two things and should not be read as a via_ir result. Tests dominated by contract deployment fall sharply, up to 195k, since the bytecode is smaller. The Safe-based end to end tests rise by around 110k, which is upstream v1.5.0 being different code from the fork rather than anything the IR pipeline did. The median entry moves +2.72%, so runtime gas is not uniformly better. Six new entries: the suite gained tests since this file was last generated. Generated with the seed CI pins, so fuzz entries are reproducible. --- .gas-snapshot | 344 +++++++++++++++++++++++++------------------------- 1 file changed, 172 insertions(+), 172 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 8e87ad82..b633ec6c 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,172 +1,172 @@ -BaseComposableCowTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10756) -BaseComposableCowTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17449) -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: 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: 1578967) -ComposableCowDiscoveryTest:test_module_RevertsContentAddressedWithURI() (gas: 39842) -ComposableCowDiscoveryTest:test_module_RevertsSha256WithoutURI() (gas: 38851) -ComposableCowDiscoveryTest:test_module_RevertsUncommittedURI() (gas: 39797) -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: 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, μ: 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: 116257) -ComposableCowManifestTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10757) -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: 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: 1469832) -ComposableCowManifestTest:test_manifestPage_EmptyPageCarriesWaitReason() (gas: 1497793) -ComposableCowManifestTest:test_manifestPage_OutOfRangeTerminates() (gas: 1552113) -ComposableCowManifestTest:test_manifest_DoesNotPerturbGeneratorInterfaceId() (gas: 325) -ComposableCowManifestTest:test_manifest_SupportsInterface() (gas: 1545467) -ComposableCowPollTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10778) -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: 1521666) -ComposableCowPollTest:test_tryGenerateOrder_ReturnsFullCustomErrorData() (gas: 1427007) -ComposableCowPollTest:test_tryGenerateOrder_ReturnsFullErrorString() (gas: 1448273) -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: 10778) -ComposableCowProofTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17449) -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, μ: 27817, ~: 27817) -ComposableCowStopLossTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 10757) -ComposableCowStopLossTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 17449) -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, μ: 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, μ: 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, μ: 90887, ~: 91957) -ComposableCowTest:test_getTradeableOrderWithSignature_FuzzRevertInvalidSingleOrder(address,address,bytes32,bytes) (runs: 256, μ: 18522, ~: 18502) -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, μ: 72842, ~: 72842) -ComposableCowTest:test_setRootWithContext_e2e() (gas: 13430581) -ComposableCowTest:test_setRoot_FuzzSetAndEmit(address,bytes32) (runs: 256, μ: 41225, ~: 41225) -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, μ: 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: 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, μ: 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: 19043) -ComposableCowTwapTest:test_getNextPollTimestamp_RevertOnZeroFrequency() (gas: 18475) -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 +BaseComposableCowTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 11261) +BaseComposableCowTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 18105) +ComposableCowDescriptorDocTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 11305) +ComposableCowDescriptorDocTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 18187) +ComposableCowDescriptorDocTest:test_descriptor_ComponentCountMatchesEncodedWidth() (gas: 50876) +ComposableCowDescriptorDocTest:test_descriptor_ObservedReasonCodeIsDocumented() (gas: 120414) +ComposableCowDescriptorDocTest:test_descriptor_SelectorMatchesDeclaredName() (gas: 182973) +ComposableCowDescriptorDocTest:test_descriptor_SelectorsAreDistinct() (gas: 163733) +ComposableCowDiscoveryTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 11305) +ComposableCowDiscoveryTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 18325) +ComposableCowDiscoveryTest:test_descriptor_CommittedAdvertisesAndRoundTrips() (gas: 2033244) +ComposableCowDiscoveryTest:test_descriptor_ConstructorEmitsUpdate() (gas: 2027846) +ComposableCowDiscoveryTest:test_descriptor_UncommittedDoesNotAdvertise() (gas: 1931847) +ComposableCowDiscoveryTest:test_module_CommittedAdvertisesAndRoundTrips() (gas: 1498629) +ComposableCowDiscoveryTest:test_module_ContentAddressedNeedsNoURI() (gas: 1398108) +ComposableCowDiscoveryTest:test_module_NeedsInputSignal() (gas: 1405789) +ComposableCowDiscoveryTest:test_module_RevertsContentAddressedWithURI() (gas: 39723) +ComposableCowDiscoveryTest:test_module_RevertsSha256WithoutURI() (gas: 38899) +ComposableCowDiscoveryTest:test_module_RevertsUncommittedURI() (gas: 40273) +ComposableCowDiscoveryTest:test_module_UncommittedDoesNotAdvertise() (gas: 1395475) +ComposableCowForwarderTest:test_ERC1271Forwarder_isValidSignature_RevertsOnBadHash() (gas: 630773) +ComposableCowForwarderTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 11443) +ComposableCowForwarderTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 18481) +ComposableCowGatTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 11487) +ComposableCowGatTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 18657) +ComposableCowGatTest:test_generateOrder_FuzzContext(address,address,address,uint256,uint256,uint256,uint256,bool) (runs: 256, μ: 121421, ~: 121422) +ComposableCowGatTest:test_generateOrder_FuzzRevertBeforeStartTime(uint256,uint256) (runs: 256, μ: 21804, ~: 21804) +ComposableCowGatTest:test_generateOrder_FuzzRevertBelowMinBalance(uint256,uint256) (runs: 256, μ: 114443, ~: 114444) +ComposableCowGatTest:test_generateOrder_FuzzRevertTooLowOutput(uint256,uint256,uint256) (runs: 256, μ: 124247, ~: 124317) +ComposableCowGatTest:test_generateOrder_RevertZeroAmount() (gas: 113369) +ComposableCowGatTest:test_generateOrder_e2e_Fuzz(uint256,uint256,uint256,uint256,uint256,uint256) (runs: 256, μ: 299380, ~: 299347) +ComposableCowGatTest:test_generateOrder_e2e_FuzzWithPriceChecker(uint256,uint256,uint256,uint256,uint256) (runs: 256, μ: 308734, ~: 308599) +ComposableCowGatTest:test_pollHints_SingleShot() (gas: 16098) +ComposableCowGatTest:test_settle_e2e() (gas: 491422) +ComposableCowGatTest:test_verify_e2e_fuzz(uint256,uint256,uint256,uint256,uint256) (runs: 256, μ: 137170, ~: 137035) +ComposableCowGuardsTest:test_BaseSwapGuard_supportsInterface() (gas: 138710) +ComposableCowGuardsTest:test_ReceiverLock_verify_FuzzRevertsWhenReceiverNotSelf(address) (runs: 256, μ: 299508, ~: 299508) +ComposableCowGuardsTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 11487) +ComposableCowGuardsTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 18546) +ComposableCowGuardsTest:test_setSwapGuard_FuzzSetAndEmit(address,address) (runs: 256, μ: 31252, ~: 31236) +ComposableCowGuardsTest:test_setSwapGuard_e2e() (gas: 1030524) +ComposableCowManifestTest:test_PSS_ManifestPage_NotFundedCarriesStatus() (gas: 37596) +ComposableCowManifestTest:test_PSS_ManifestPage_WithBalance() (gas: 125366) +ComposableCowManifestTest:test_PSS_ManifestReturnsUnbounded() (gas: 13902) +ComposableCowManifestTest:test_PSS_PaginationAlwaysTerminates() (gas: 125004) +ComposableCowManifestTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 11349) +ComposableCowManifestTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 18485) +ComposableCowManifestTest:test_TWAP_IsActive_DuringSpan() (gas: 37144) +ComposableCowManifestTest:test_TWAP_ManifestEntriesMatchGenerateOrder() (gas: 360743) +ComposableCowManifestTest:test_TWAP_getManifestInfo_DegenerateYieldsEmptyManifest() (gas: 17562) +ComposableCowManifestTest:test_TWAP_getManifestInfo_ReturnsExactCardinality() (gas: 18317) +ComposableCowManifestTest:test_TWAP_getManifestPage_Pagination() (gas: 154912) +ComposableCowManifestTest:test_TWAP_getManifestPage_ReturnsAllParts() (gas: 171094) +ComposableCowManifestTest:test_TWAP_getManifestPage_UninitializedCarriesStatus() (gas: 22888) +ComposableCowManifestTest:test_TWAP_getManifestPage_WithContext() (gas: 112708) +ComposableCowManifestTest:test_manifestInfo_DefaultSingleShot() (gas: 1540712) +ComposableCowManifestTest:test_manifestPage_DefaultSingleEntry() (gas: 1698609) +ComposableCowManifestTest:test_manifestPage_EmptyPageCarriesInvalidReason() (gas: 1290668) +ComposableCowManifestTest:test_manifestPage_EmptyPageCarriesWaitReason() (gas: 1330083) +ComposableCowManifestTest:test_manifestPage_OutOfRangeTerminates() (gas: 1545516) +ComposableCowManifestTest:test_manifest_DoesNotPerturbGeneratorInterfaceId() (gas: 855) +ComposableCowManifestTest:test_manifest_SupportsInterface() (gas: 1538778) +ComposableCowPollTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 11531) +ComposableCowPollTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 19119) +ComposableCowPollTest:test_checkOrder_ComposesFillOverlay() (gas: 1833894) +ComposableCowPollTest:test_checkOrder_RevertInterfaceNotSupported() (gas: 51466) +ComposableCowPollTest:test_fillOverlay_FilledWithholdsSignature() (gas: 1835512) +ComposableCowPollTest:test_fillOverlay_ForeignOwnerOrderUidNotObserved() (gas: 1860267) +ComposableCowPollTest:test_fillOverlay_InvalidatedIsDistinctFromFilled() (gas: 1834924) +ComposableCowPollTest:test_fillOverlay_KindBuyTotalIsBuyAmount() (gas: 1835470) +ComposableCowPollTest:test_fillOverlay_KindSellSameAmountIsPartial() (gas: 1850563) +ComposableCowPollTest:test_fillOverlay_NoneReturnsSignature() (gas: 1851348) +ComposableCowPollTest:test_fillOverlay_OrderUidMatchesGPv2Construction() (gas: 1841715) +ComposableCowPollTest:test_fillOverlay_PartialFillKeepsPosting() (gas: 1850375) +ComposableCowPollTest:test_fillOverlay_PartialFillOnFillOrKillWithholdsSignature() (gas: 1815449) +ComposableCowPollTest:test_getTradeableOrderWithSignature_UsesPollInternally() (gas: 1375792) +ComposableCowPollTest:test_poll_BareRequireMapsToTryNextBlock() (gas: 1250645) +ComposableCowPollTest:test_poll_DecodesOrderNotValid() (gas: 1291406) +ComposableCowPollTest:test_poll_DecodesPollNeedsOffchainInput() (gas: 1402236) +ComposableCowPollTest:test_poll_DecodesPollTryAtBlock() (gas: 1330995) +ComposableCowPollTest:test_poll_DecodesPollTryAtTimestamp() (gas: 1330907) +ComposableCowPollTest:test_poll_DecodesPollTryNextBlock() (gas: 1290285) +ComposableCowPollTest:test_poll_FuzzOrderNotValid(bytes4) (runs: 256, μ: 1283321, ~: 1291095) +ComposableCowPollTest:test_poll_FuzzPollTryAtBlock(uint256,bytes4) (runs: 256, μ: 1323038, ~: 1330890) +ComposableCowPollTest:test_poll_FuzzPollTryAtTimestamp(uint256,bytes4) (runs: 256, μ: 1323566, ~: 1331418) +ComposableCowPollTest:test_poll_NeedsInputHandlerPostsWithInput() (gas: 1404879) +ComposableCowPollTest:test_poll_PanicMapsToTryNextBlock() (gas: 1294536) +ComposableCowPollTest:test_poll_ReturnsPostOnValidOrder() (gas: 1763768) +ComposableCowPollTest:test_poll_UnknownErrorMapsToTryNextBlock() (gas: 1238223) +ComposableCowPollTest:test_tryGenerateOrder_NeedsInputRevertData() (gas: 1403695) +ComposableCowPollTest:test_tryGenerateOrder_ReturnsFullCustomErrorData() (gas: 1240499) +ComposableCowPollTest:test_tryGenerateOrder_ReturnsFullErrorString() (gas: 1252773) +ComposableCowPollTest:test_tryGenerateOrder_ReturnsFullPanicData() (gas: 1296614) +ComposableCowPollTest:test_tryGenerateOrder_SuccessReturnsOrder() (gas: 1677206) +ComposableCowPollTest:test_verify_RevertsOnHashMismatch() (gas: 1764501) +ComposableCowPollTest:test_verify_UsesGenerateOrder() (gas: 1761834) +ComposableCowProofTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 11349) +ComposableCowProofTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 18303) +ComposableCowProofTest:test_payloadTree_NormativeConstructionVerifiesLikeAuth() (gas: 573322) +ComposableCowProofTest:test_setRoot_BlobSubsetAttached() (gas: 41153) +ComposableCowProofTest:test_setRoot_BlobsAttached() (gas: 42837) +ComposableCowProofTest:test_setRoot_EmitsUriMirrors() (gas: 48180) +ComposableCowProofTest:test_setRoot_RevertsBlobNotAttached() (gas: 14819) +ComposableCowProofTest:test_setRoot_RevertsBlobNotAttachedNoBlobs() (gas: 13210) +ComposableCowProofTest:test_setRoot_RevertsZeroRootWithBlobs() (gas: 13352) +ComposableCowProofTest:test_setRoot_RevertsZeroRootWithUris() (gas: 12726) +ComposableCowProofTest:test_setRoot_ZeroRootClears() (gas: 32859) +ComposableCowStopLossTest:test_OracleNormalisesPrice_concrete() (gas: 27435) +ComposableCowStopLossTest:test_OracleNormalisesPrice_fuzz(uint8,uint8,uint8,uint8) (runs: 256, μ: 29597, ~: 29613) +ComposableCowStopLossTest:test_OracleRevertOnExpiredOrder_fuzz(uint32,uint32) (runs: 256, μ: 23185, ~: 23185) +ComposableCowStopLossTest:test_OracleRevertOnInvalidPrice_fuzz(int256,int256) (runs: 256, μ: 36635, ~: 36635) +ComposableCowStopLossTest:test_OracleRevertOnStalePrice_fuzz(uint256,uint256,uint256) (runs: 256, μ: 25348, ~: 25348) +ComposableCowStopLossTest:test_RevertStrikePriceNotMet_fuzz(int256,int256,int256,uint256,uint256) (runs: 256, μ: 28465, ~: 28465) +ComposableCowStopLossTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 11283) +ComposableCowStopLossTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 18353) +ComposableCowStopLossTest:test_generateOrder_RevertZeroAmount() (gas: 22286) +ComposableCowStopLossTest:test_pollHints_SingleShot() (gas: 15780) +ComposableCowStopLossTest:test_strikePriceMet_fuzz(int256,int256,int256,uint32) (runs: 256, μ: 29077, ~: 29077) +ComposableCowStopLossTest:test_strikePriceNotMet_concrete() (gas: 26555) +ComposableCowTatTest:test_BalanceMet_fuzz(address,uint256,bytes32,uint256) (runs: 256, μ: 113409, ~: 113392) +ComposableCowTatTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 11283) +ComposableCowTatTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 18177) +ComposableCowTatTest:test_generateOrder_FuzzRevertBelowThreshold(uint256,uint256) (runs: 256, μ: 111614, ~: 111616) +ComposableCowTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 11575) +ComposableCowTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 18877) +ComposableCowTest:test_createAndRemove_FuzzSetAndEmit(address,address,bytes32,bytes) (runs: 256, μ: 40044, ~: 39905) +ComposableCowTest:test_createAndRemove_e2e() (gas: 468147) +ComposableCowTest:test_createWithContextAndRemove_FuzzSetAndEmit(address,address,bytes32,bytes,bytes32) (runs: 256, μ: 63585, ~: 63575) +ComposableCowTest:test_create_RevertOnInvalidHandler() (gas: 10433) +ComposableCowTest:test_getTradeableOrderWithSignature_FuzzRevertInvalidProof(address,bytes32[],bytes32,address,bytes32,bytes) (runs: 256, μ: 97806, ~: 99033) +ComposableCowTest:test_getTradeableOrderWithSignature_FuzzRevertInvalidSingleOrder(address,address,bytes32,bytes) (runs: 256, μ: 18665, ~: 18645) +ComposableCowTest:test_getTradeableOrderWithSignature_ReturnsValidPayloadForNonSafe() (gas: 642433) +ComposableCowTest:test_getTradeableOrderWithSignature_ReturnsValidPayloadForSafe() (gas: 109925) +ComposableCowTest:test_getTradeableOrderWithSignature_RevertInterfaceNotSupported() (gas: 52460) +ComposableCowTest:test_isValidSafeSignature_BaseConditionalOrder_RevertOnInvalidHash() (gas: 60749) +ComposableCowTest:test_isValidSafeSignature_FuzzPassesContextToHandler(address,bytes32) (runs: 256, μ: 57674, ~: 57674) +ComposableCowTest:test_isValidSafeSignature_FuzzRevertInvalidProof(address,bytes32[],bytes32,address,bytes32,bytes) (runs: 256, μ: 99444, ~: 100634) +ComposableCowTest:test_isValidSafeSignature_FuzzRevertInvalidSingleOrder(address,address,bytes32,bytes) (runs: 256, μ: 18645, ~: 18618) +ComposableCowTest:test_remove_EmitsConditionalOrderRemoved() (gas: 36281) +ComposableCowTest:test_remove_FuzzEmitsEvent(address,bytes32) (runs: 256, μ: 31572, ~: 31546) +ComposableCowTest:test_safeSignaturePayload_SelectorMatchesMuxerMagicValue() (gas: 1145) +ComposableCowTest:test_setRootWithContext_FuzzSetAndEmit(address,bytes32,bytes32) (runs: 256, μ: 73774, ~: 73774) +ComposableCowTest:test_setRootWithContext_e2e() (gas: 13600334) +ComposableCowTest:test_setRoot_FuzzSetAndEmit(address,bytes32) (runs: 256, μ: 42105, ~: 42105) +ComposableCowTest:test_setRoot_e2e() (gas: 13568973) +ComposableCowTwapTest:test_SetUpState_ComposableCowDomainSeparator_is_set() (gas: 11488) +ComposableCowTwapTest:test_SetUpState_ComposableCowDomainVerifier_is_set() (gas: 18987) +ComposableCowTwapTest:test_TWAPOrderMathLib_calculateValidTo(uint256,uint256,uint256,uint256,uint256) (runs: 256, μ: 12678, ~: 12784) +ComposableCowTwapTest:test_describeOrder_RevertOnZeroFrequency() (gas: 21049) +ComposableCowTwapTest:test_describeOrder_TwapParts() (gas: 29107) +ComposableCowTwapTest:test_generateOrder_FuzzRevertIfBeforeStart(uint256,uint256) (runs: 256, μ: 29035, ~: 29035) +ComposableCowTwapTest:test_generateOrder_FuzzRevertIfExpired(uint256,uint256) (runs: 256, μ: 30430, ~: 30108) +ComposableCowTwapTest:test_generateOrder_FuzzRevertIfOrderAfterBlocktimestampValidity(uint256,uint256) (runs: 256, μ: 186369, ~: 187178) +ComposableCowTwapTest:test_generateOrder_FuzzRevertIfOrderBeforeBlockTimestamp(uint256,uint256) (runs: 256, μ: 187292, ~: 187292) +ComposableCowTwapTest:test_generateOrder_FuzzRevertIfOutsideSpan(uint256,uint256) (runs: 256, μ: 32310, ~: 32137) +ComposableCowTwapTest:test_generateOrder_FuzzRevertOnInvalidFrequency(uint256) (runs: 256, μ: 19746, ~: 19747) +ComposableCowTwapTest:test_generateOrder_FuzzRevertOnInvalidNumParts(uint256) (runs: 256, μ: 19603, ~: 19605) +ComposableCowTwapTest:test_generateOrder_FuzzRevertOnInvalidSpan(uint256,uint256) (runs: 256, μ: 20164, ~: 20164) +ComposableCowTwapTest:test_generateOrder_FuzzRevertOnInvalidStartTime(uint256) (runs: 256, μ: 19006, ~: 19006) +ComposableCowTwapTest:test_generateOrder_RevertOnSameTokens() (gas: 18983) +ComposableCowTwapTest:test_generateOrder_RevertOnTokenZero() (gas: 24954) +ComposableCowTwapTest:test_generateOrder_RevertOnZeroMinPartLimit() (gas: 19268) +ComposableCowTwapTest:test_generateOrder_RevertOnZeroPartSellAmount() (gas: 19364) +ComposableCowTwapTest:test_generateOrder_e2e_fuzz(uint256,uint256) (runs: 256, μ: 203752, ~: 203484) +ComposableCowTwapTest:test_generateOrder_e2e_fuzz_WithContext(uint32,uint256) (runs: 256, μ: 233400, ~: 236324) +ComposableCowTwapTest:test_getNextPollTimestamp_FinalPartStopsPolling() (gas: 19664) +ComposableCowTwapTest:test_getNextPollTimestamp_PointsAtNextPart() (gas: 20153) +ComposableCowTwapTest:test_getNextPollTimestamp_RevertOnZeroFrequency() (gas: 19285) +ComposableCowTwapTest:test_getNextPollTimestamp_RevertOnZeroNumParts() (gas: 19451) +ComposableCowTwapTest:test_settle_e2e() (gas: 13514775) +ComposableCowTwapTest:test_simulate_fuzz(uint32,uint32,uint32) (runs: 256, μ: 20411289, ~: 20821712) +ComposableCowTwapTest:test_verify_e2e_fuzz(uint256,uint256) (runs: 256, μ: 36266, ~: 35995) \ No newline at end of file From a8aa78acd34dddbcfaff8086c288042e9c4aee02 Mon Sep 17 00:00:00 2001 From: mfw78 Date: Mon, 3 Aug 2026 03:10:46 +0000 Subject: [PATCH 4/4] docs: name the tree builders that do not produce the normative shape `leafEncoding: "v1"` fixes the tree shape, but sorted-pair verification is shape-agnostic, so a tree built by the wrong library still verifies against its own root. The divergence only surfaces when a consumer recomputes `root` from `leaves`, which the payload rules require. Solady's `MerkleTreeLib` builds a complete 2n-1 node tree and diverges from the odd-promotion construction at 5, 7 and 9 leaves (measured; 2, 3, 4, 6 and 8 agree). It now ships as a dependency, so it is the likeliest wrong turn for an integrator, alongside OpenZeppelin's `StandardMerkleTree`. --- docs/discovery.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/discovery.md b/docs/discovery.md index cb7fc27e..b0804a11 100644 --- a/docs/discovery.md +++ b/docs/discovery.md @@ -639,12 +639,17 @@ 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))`; 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` - double-hashes leaves and yields different roots; it is NOT this encoding). - Reference test vectors are published alongside the contracts. + `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, so implementations MUST follow this construction. Neither + OpenZeppelin's `StandardMerkleTree` (it double-hashes leaves) nor Solady's + `MerkleTreeLib` (it builds a complete `2n-1` node tree, diverging wherever + the odd-promotion rule fires, such as at 5, 7 or 9 leaves) produces this + shape. The mismatch is silent under verification: `MerkleProofLib.verify` is + sorted-pair and therefore shape-agnostic, so a non-conforming tree still + verifies against its own root, and the divergence surfaces only when a + consumer recomputes `root` from `leaves`. Reference test vectors are + published alongside the contracts. - `leaves` MUST be sorted ascending by leaf hash and deduplicated; consumers MUST reject on the first out-of-order or duplicate leaf. - Producers MUST serialize with RFC 8785; content addresses and digests commit