@@ -23,14 +23,6 @@ contract MockAuthentication {
2323}
2424
2525contract MockSettlement {
26- struct SettleCall {
27- IERC20 [] tokens;
28- uint256 [] clearingPrices;
29- GPv2Trade.Data[] trades;
30- bytes origData;
31- }
32-
33- SettleCall[] public settleCalls;
3426 CowAuthentication private immutable _authenticator;
3527
3628 constructor (CowAuthentication authenticator_ ) {
@@ -42,35 +34,11 @@ contract MockSettlement {
4234 }
4335
4436 function settle (
45- IERC20 [] calldata tokens ,
46- uint256 [] calldata clearingPrices ,
47- GPv2Trade.Data[] calldata trades ,
48- GPv2Interaction.Data[][3 ] calldata interactions
49- ) external {
50- SettleCall storage call_ = settleCalls.push ();
51- call_.tokens = tokens;
52- call_.clearingPrices = clearingPrices;
53-
54- for (uint256 i = 0 ; i < trades.length ; i++ ) {
55- call_.trades.push (trades[i]);
56- }
57-
58- call_.origData = msg .data ;
59- }
60-
61- function getSettleCallCount () external view returns (uint256 ) {
62- return settleCalls.length ;
63- }
64-
65- function getLastSettleCall ()
66- external
67- view
68- returns (uint256 tokenCount , uint256 priceCount , uint256 tradeCount , bytes memory origData )
69- {
70- require (settleCalls.length > 0 , "No settle calls " );
71- SettleCall storage lastCall = settleCalls[settleCalls.length - 1 ];
72- return (lastCall.tokens.length , lastCall.clearingPrices.length , lastCall.trades.length , lastCall.origData);
73- }
37+ IERC20 [] calldata ,
38+ uint256 [] calldata ,
39+ GPv2Trade.Data[] calldata ,
40+ GPv2Interaction.Data[][3 ] calldata
41+ ) external {}
7442}
7543
7644// Test wrapper that exposes internal functions
@@ -103,14 +71,6 @@ contract TestWrapper is CowWrapper {
10371 function exposed_internalSettle (bytes calldata settleData , bytes calldata wrapperData ) external {
10472 _internalSettle (settleData, wrapperData);
10573 }
106-
107- function getWrapCallCount () external view returns (uint256 ) {
108- return wrapCalls.length ;
109- }
110-
111- function getWrapCall (uint256 index ) external view returns (bytes memory settleData , bytes memory wrapperData ) {
112- return (wrapCalls[index].settleData, wrapCalls[index].wrapperData);
113- }
11474}
11575
11676contract CowWrapperTest is Test {
@@ -161,36 +121,24 @@ contract CowWrapperTest is Test {
161121 );
162122 }
163123
164- function test_wrap_ReceivesCorrectParameters () public {
165- bytes memory customWrapperData = hex "deadbeef " ;
166- bytes memory settleData = _createSimpleSettleData (1 );
167- // wrapperData is just custom data - no settlement address needed
168- bytes memory wrapperData = abi.encodePacked (uint16 (customWrapperData.length ), customWrapperData);
124+ function test_internalSettle_CallsWrapperAndThenNextSettlement () public {
125+ bytes memory settleData = abi.encodePacked (_createSimpleSettleData (1 ), hex "123456 " );
126+ bytes memory secondCallWrapperData = hex "0003098765 " ;
127+ bytes memory wrapperData = abi.encodePacked (hex "00021234 " , address (testWrapper), secondCallWrapperData);
169128
170- vm. prank (solver);
171- testWrapper. wrappedSettle (settleData, wrapperData );
129+ // the wrapper gets called exactly twice (once below and again inside the wrapper data calling self)
130+ vm. expectCall ( address ( testWrapper), 0 , abi.encodeWithSelector (testWrapper.wrappedSettle. selector ), 2 );
172131
173- assertEq (testWrapper.getWrapCallCount (), 1 );
174- (bytes memory recordedSettleData , bytes memory recordedWrapperData ) = testWrapper.getWrapCall (0 );
175- assertGt (recordedSettleData.length , 0 );
176- assertEq (recordedWrapperData, customWrapperData);
177- }
132+ // verify the internal wrapper call data
133+ vm.expectCall (address (testWrapper), abi.encodeWithSelector (testWrapper.wrappedSettle.selector , settleData, secondCallWrapperData));
178134
179- function test_internalSettle_CallsNextSettlement () public {
180- bytes memory settleData = abi.encodePacked (_createSimpleSettleData (1 ), hex "123456 " );
181- // Empty wrapperData means call the static SETTLEMENT contract
182- bytes memory wrapperData = hex "0000 " ;
135+ // the settlement contract gets called once after wrappers (including the surplus data at the end)
136+ vm.expectCall (address (mockSettlement), 0 , settleData, 1 );
183137
184138 vm.prank (solver);
185139 testWrapper.wrappedSettle (settleData, wrapperData);
186-
187- assertEq (mockSettlement.getSettleCallCount (), 1 );
188- (uint256 tokenCount , uint256 priceCount , uint256 tradeCount , bytes memory origData ) = mockSettlement.getLastSettleCall ();
189- assertEq (tokenCount, 1 );
190- assertEq (priceCount, 1 );
191- assertEq (tradeCount, 0 );
192- assertEq (origData, settleData);
193140 }
141+
194142
195143 function test_wrappedSettle_RevertsWithNotASolver () public {
196144 bytes memory settleData = _createSimpleSettleData (0 );
@@ -203,6 +151,7 @@ contract CowWrapperTest is Test {
203151 }
204152
205153 function test_integration_ThreeWrappersChained () public {
154+ // Set up a more sophisticated settlement call to make sure it all gets through as expected.
206155 CowWrapperHelpers.SettleCall memory settlement;
207156 settlement.tokens = new address [](2 );
208157 settlement.tokens[0 ] = address (0x1 );
@@ -233,27 +182,32 @@ contract CowWrapperTest is Test {
233182 ];
234183
235184 // Build the chained wrapper data:
236- // solver -> wrapper1 -> wrapper2 -> wrapper3 -> mockSettlement
237- address [] memory wrappers = new address [](3 );
185+ // solver -> wrapper1 -> wrapper2 -> wrapper1 -> wrapper3 -> mockSettlement
186+ address [] memory wrappers = new address [](4 );
238187 wrappers[0 ] = address (wrapper1);
239188 wrappers[1 ] = address (wrapper2);
240- wrappers[2 ] = address (wrapper3);
189+ wrappers[2 ] = address (wrapper1);
190+ wrappers[3 ] = address (wrapper3);
191+
192+ bytes [] memory datas = new bytes [](4 );
193+
194+ datas[2 ] = hex "828348 " ;
241195
242196 (address target , bytes memory fullCalldata ) =
243- CowWrapperHelpers.encodeWrapperCall (wrappers, new bytes [](3 ), address (mockSettlement), settlement);
197+ CowWrapperHelpers.encodeWrapperCall (wrappers, datas, address (mockSettlement), settlement);
198+
199+
200+ // all the wrappers gets called, with wrapper 1 called twice
201+ vm.expectCall (address (wrapper1), 0 , abi.encodeWithSelector (testWrapper.wrappedSettle.selector ), 2 );
202+ vm.expectCall (address (wrapper2), 0 , abi.encodeWithSelector (testWrapper.wrappedSettle.selector ), 1 );
203+ vm.expectCall (address (wrapper3), 0 , abi.encodeWithSelector (testWrapper.wrappedSettle.selector ), 1 );
204+
205+ // the settlement gets called with the full data
206+ vm.expectCall (address (mockSettlement), new bytes (0 ));
244207
245208 // Call wrapper1 as the solver
246209 vm.prank (solver);
247210 (bool success ,) = target.call (fullCalldata);
248211 assertTrue (success, "Chained wrapper call should succeed " );
249-
250- // Verify that mockSettlement was called
251- assertEq (mockSettlement.getSettleCallCount (), 1 , "MockSettlement should be called once " );
252-
253- // Verify the settlement received the correct parameters
254- (uint256 tokenCount , uint256 priceCount , uint256 tradeCount ,) = mockSettlement.getLastSettleCall ();
255- assertEq (tokenCount, 2 , "Should have 2 tokens " );
256- assertEq (priceCount, 2 , "Should have 2 prices " );
257- assertEq (tradeCount, 1 , "Should have 1 trade " );
258212 }
259213}
0 commit comments