Skip to content

Commit 41ddd46

Browse files
committed
clarify the thing that is being tested and use expectCall more
1 parent 8529191 commit 41ddd46

File tree

1 file changed

+35
-81
lines changed

1 file changed

+35
-81
lines changed

test/CowWrapper.t.sol

Lines changed: 35 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,6 @@ contract MockAuthentication {
2323
}
2424

2525
contract 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

11676
contract 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

Comments
 (0)